From 14ad0d45a2aa4b37727f332a352f2854d6493502 Mon Sep 17 00:00:00 2001 From: Stefano Apostolico Date: Fri, 7 Feb 2025 10:17:26 +0100 Subject: [PATCH 01/14] add typing --- .bumpversion.cfg | 2 +- .github/workflows/test.yml | 4 +- .gitignore | 7 +- .pre-commit-config.yaml | 21 - AUTHORS.rst | 1 - CHANGES | 4 + Makefile | 3 +- README.md | 32 +- docs/source/_ext/djangodocs.py | 51 +- docs/source/_ext/github.py | 56 +- docs/source/_ext/version.py | 8 +- docs/source/changes.rst | 1 - docs/source/conf.py | 8 +- docs/source/exceptions.rst | 1 - docs/source/faq.rst | 3 - docs/source/howto.rst | 1 - docs/source/install.rst | 2 +- docs/source/permissions.rst | 1 - manage.py | 8 +- pyproject.toml | 147 +- setup.cfg | 43 - setup.py | 63 - src/adminactions/actions.py | 8 +- src/adminactions/api.py | 129 +- src/adminactions/apps.py | 2 +- src/adminactions/bulk_update.py | 44 +- src/adminactions/byrows_update.py | 19 +- src/adminactions/checks.py | 5 +- src/adminactions/duplicates.py | 23 +- src/adminactions/export.py | 64 +- src/adminactions/forms.py | 20 +- src/adminactions/graph.py | 11 +- src/adminactions/helpers.py | 15 +- .../commands/create_extra_permissions.py | 4 +- src/adminactions/mass_update.py | 131 +- src/adminactions/merge.py | 62 +- src/adminactions/models.py | 5 +- src/adminactions/perms.py | 14 +- src/adminactions/py.typed | 0 .../static/adminactions/css/adminactions.css | 51 +- .../adminactions/css/adminactions.css.map | 2 +- .../static/adminactions/css/adminactions.scss | 13 +- .../static/adminactions/css/bulkupdate.css | 30 +- .../adminactions/css/bulkupdate.css.map | 2 +- .../static/adminactions/css/bulkupdate.scss | 6 +- .../static/adminactions/css/massupdate.css | 21 +- .../adminactions/css/massupdate.css.map | 2 +- .../static/adminactions/css/massupdate.scss | 1 - .../static/adminactions/js/bulkupdate.js | 9 +- .../adminactions/js/jqplot/MIT-LICENSE.txt | 2 +- .../static/adminactions/js/jqplot/README.txt | 22 +- .../adminactions/js/jqplot/jquery.jqplot.css | 93 +- .../js/jqplot/jquery.jqplot.min.css | 221 +- .../js/jqplot/jquery.jqplot.min.js | 9969 ++++++++++++++++- .../js/jqplot/plugins/jqplot.barRenderer.js | 739 +- .../jqplot/plugins/jqplot.barRenderer.min.js | 715 +- .../plugins/jqplot.categoryAxisRenderer.js | 641 +- .../jqplot.categoryAxisRenderer.min.js | 603 +- .../js/jqplot/plugins/jqplot.pieRenderer.js | 770 +- .../jqplot/plugins/jqplot.pieRenderer.min.js | 712 +- .../static/adminactions/js/massupdate.js | 84 +- .../static/adminactions/js/massupdate.min.js | 75 +- .../static/adminactions/js/merge.js | 94 +- .../static/adminactions/js/merge.min.js | 96 +- src/adminactions/tasks.py | 6 +- src/adminactions/templates/500.html | 11 +- .../templates/adminactions/any_model.html | 12 +- .../templates/adminactions/bulk_update.html | 193 +- .../adminactions/bulk_update_results.html | 76 +- .../templates/adminactions/byrows_update.html | 136 +- .../templates/adminactions/charts.html | 101 +- .../templates/adminactions/duplicates.html | 90 +- .../templates/adminactions/export_csv.html | 576 +- .../adminactions/export_fixture.html | 54 +- .../templates/adminactions/export_xls.html | 77 +- .../adminactions/helpers/import_fixture.html | 41 +- .../templates/adminactions/mass_update.html | 155 +- .../templates/adminactions/merge.html | 33 +- .../templates/adminactions/merge_preview.html | 77 +- src/adminactions/templatetags/aa_compat.py | 3 +- src/adminactions/templatetags/actions.py | 13 +- src/adminactions/templatetags/massupdate.py | 18 +- src/adminactions/templatetags/merge.py | 13 +- src/adminactions/utils.py | 87 +- src/adminactions/views.py | 3 +- src/requirements/develop.pip | 7 - src/requirements/install.pip | 3 - src/requirements/rtd.pip | 3 - src/requirements/testing.pip | 24 - tests/conftest.py | 28 +- tests/demo/apps.py | 4 +- tests/demo/backends.py | 15 +- tests/demo/celery.py | 2 + tests/demo/fixtures/adminactions.json | 463 +- tests/demo/fixtures/demoproject.json | 154 +- tests/demo/migrations/0001_initial.py | 19 +- tests/demo/models.py | 4 +- tests/demo/settings.py | 140 +- tests/demo/storage.py | 9 +- tests/demo/urls.py | 3 +- tests/selenium_tests/conftest.py | 8 +- tests/selenium_tests/test_export_csv.py | 16 +- tests/selenium_tests/test_export_xls.py | 2 + tests/selenium_tests/test_mass_update.py | 10 +- tests/test_api.py | 70 +- tests/test_bulk_update.py | 208 +- tests/test_byrows_update.py | 27 +- tests/test_duplicates.py | 8 +- tests/test_exports.py | 203 +- tests/test_graph.py | 12 +- tests/test_mass_update.py | 71 +- tests/test_merge.py | 130 +- tests/test_permissions.py | 18 +- tests/test_templatetags.py | 6 +- tests/test_transaction.py | 32 +- tests/test_utils.py | 6 +- tests/test_views.py | 10 +- tests/utils.py | 86 +- tox.ini | 100 +- uv.lock | 1199 ++ 120 files changed, 17563 insertions(+), 3308 deletions(-) delete mode 100644 .pre-commit-config.yaml delete mode 100644 setup.cfg delete mode 100755 setup.py create mode 100644 src/adminactions/py.typed delete mode 100644 src/requirements/develop.pip delete mode 100644 src/requirements/install.pip delete mode 100644 src/requirements/rtd.pip delete mode 100644 src/requirements/testing.pip create mode 100644 uv.lock diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 5f8196e9..6b60f498 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -10,7 +10,7 @@ allow_dirty = True [bumpversion:part:release] optional_value = final -values = +values = dev rc final diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 75aa4a30..111ea1d6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -30,8 +30,8 @@ jobs: strategy: fail-fast: false matrix: - python-version: [ "3.9", "3.10", "3.11" ] - django-version: [ "3.2", "4.2" ] + python-version: [ "3.10", "3.11", "3.12" ] + django-version: [ "3.2", "4.2", "5.0" ] env: PY_VER: ${{ matrix.python-version}} DJ_VER: ${{ matrix.django-version}} diff --git a/.gitignore b/.gitignore index 706cdcf2..2aebfd35 100644 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,10 @@ -.DS_Store +.* ~* *.log *.pot *.pyc *.egg-info *.sqlite -.idea -.tox -.cache -.coverage /dist /build /docs/build @@ -20,3 +16,4 @@ Pipfile Pipfile.lock poetry.lock .venv/ +pdm.lock diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml deleted file mode 100644 index 21df7fb2..00000000 --- a/.pre-commit-config.yaml +++ /dev/null @@ -1,21 +0,0 @@ -repos: -- repo: local - hooks: - # Configuration for black exists in pyproject.toml, - # but we let pre-commit take care of the file filtering. - - id: black - name: black - entry: black - language: python - types: [python] - require_serial: true - - id: isort - name: isort - entry: isort - language: python - types: [python] - - id: flake8 - name: flake8 - entry: flake8 - language: python - types: [python] diff --git a/AUTHORS.rst b/AUTHORS.rst index d5679886..cad54afe 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -44,4 +44,3 @@ Contributors .. _`@asfaltboy`: https://github.com/asfaltboy .. _`@int-ua`: https://github.com/int-ua .. _`@Djailla`: https://github.com/Djailla - diff --git a/CHANGES b/CHANGES index 7aa0c180..f91205e2 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +Release 2.4 (dev) +================= +* fixes #227 + Release 2.3 =========== * Add support to foreignkeys to bulk updates ( @see https://github.com/saxix/django-adminactions/pull/224/files) diff --git a/Makefile b/Makefile index b591735d..7fc7bdc7 100644 --- a/Makefile +++ b/Makefile @@ -33,8 +33,7 @@ demo: PYTHONPATH=${PWD}:${PWD}/tests:${PWD}/src django-admin.py runserver --settings=demo.settings lint: - @flake8 src/ tests/ - @isort -c src/ + pre-commit run --all clean: diff --git a/README.md b/README.md index 6e3cfe0d..65bd574c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,4 @@ -django-adminactions -=================== - +# django-adminactions [![Pypi](https://badge.fury.io/py/django-adminactions.svg)](https://badge.fury.io/py/django-adminactions) [![coverage](https://codecov.io/github/saxix/django-adminactions/coverage.svg?branch=develop)](https://codecov.io/github/saxix/django-adminactions?branch=develop) @@ -14,21 +12,19 @@ Please see the changelog at http://django-adminactions.readthedocs.org/en/latest #### Actions -* Export as CSV -* Export as Excel -* Export as fixture -* Export delete tree -* Mass update records -* Graph queryset -* Merge records -* Find Duplicates -* Bulk Update - +- Export as CSV +- Export as Excel +- Export as fixture +- Export delete tree +- Mass update records +- Graph queryset +- Merge records +- Find Duplicates +- Bulk Update #### Project Links - -- Code: https://github.com/saxix/django-adminactions -- Documentation: https://django-adminactions.readthedocs.org/en/latest/ -- Issue Tracker: https://github.com/saxix/django-adminactions/issues?sort -- Download Package: https://pypi.org/project/django-adminactions/ +- Code: https://github.com/saxix/django-adminactions +- Documentation: https://django-adminactions.readthedocs.org/en/latest/ +- Issue Tracker: https://github.com/saxix/django-adminactions/issues?sort +- Download Package: https://pypi.org/project/django-adminactions/ diff --git a/docs/source/_ext/djangodocs.py b/docs/source/_ext/djangodocs.py index 5579940d..8e698905 100644 --- a/docs/source/_ext/djangodocs.py +++ b/docs/source/_ext/djangodocs.py @@ -1,6 +1,7 @@ -""" -Sphinx plugins for Django documentation. -""" +"""Sphinx plugins for Django documentation.""" + +from __future__ import annotations + import json import os import re @@ -16,7 +17,7 @@ simple_option_desc_re = re.compile(r"([-_a-zA-Z0-9]+)(\s*.*?)(?=,\s+(?:/|-|--)|$)") -def setup(app): +def setup(app) -> None: app.add_crossref_type( directivename="setting", rolename="setting", @@ -77,39 +78,37 @@ def run(self): node.extend(inodes) if self.content: self.state.nested_parse(self.content, self.content_offset, node) - ret = ret + messages + ret += messages env.note_versionchange(node["type"], node["version"], node, self.lineno) return ret class DjangoHTMLTranslator(SmartyPantsHTMLTranslator): - """ - Django-specific reST to HTML tweaks. - """ + """Django-specific reST to HTML tweaks.""" # Don't use border=1, which docutils does by default. - def visit_table(self, node): + def visit_table(self, node) -> None: self._table_row_index = 0 # Needed by Sphinx self.body.append(self.starttag(node, "table", CLASS="docutils")) # ? Really? - def visit_desc_parameterlist(self, node): + def visit_desc_parameterlist(self, node) -> None: self.body.append("(") self.first_param = 1 self.param_separator = node.child_text_separator - def depart_desc_parameterlist(self, node): + def depart_desc_parameterlist(self, node) -> None: self.body.append(")") if sphinx_ver < "1.0.8": # # Don't apply smartypants to literal blocks # - def visit_literal_block(self, node): + def visit_literal_block(self, node) -> None: self.no_smarty += 1 SmartyPantsHTMLTranslator.visit_literal_block(self, node) - def depart_literal_block(self, node): + def depart_literal_block(self, node) -> None: SmartyPantsHTMLTranslator.depart_literal_block(self, node) self.no_smarty -= 1 @@ -128,19 +127,19 @@ def depart_literal_block(self, node): "versionadded": "New in Django %s", } - def visit_versionmodified(self, node): + def visit_versionmodified(self, node) -> None: self.body.append(self.starttag(node, "div", CLASS=node["type"])) - title = "%s%s" % ( + title = "{}{}".format( self.version_text[node["type"]] % node["version"], - len(node) and ":" or ".", + (len(node) and ":") or ".", ) - self.body.append('%s ' % title) + self.body.append(f'{title} ') - def depart_versionmodified(self, node): + def depart_versionmodified(self, node) -> None: self.body.append("\n") # Give each section a unique ID -- nice for custom CSS hooks - def visit_section(self, node): + def visit_section(self, node) -> None: old_ids = node.get("ids", []) node["ids"] = ["s-" + i for i in old_ids] node["ids"].extend(old_ids) @@ -151,13 +150,13 @@ def visit_section(self, node): def parse_django_admin_node(env, sig, signode): command = sig.split(" ")[0] env._django_curr_admin_command = command - title = "django-admin.py %s" % sig + title = f"django-admin.py {sig}" signode += addnodes.desc_name(title, title) return sig def parse_django_adminopt_node(env, sig, signode): - """A copy of sphinx.directives.CmdoptionDesc.parse_signature()""" + """A copy of sphinx.directives.CmdoptionDesc.parse_signature().""" from sphinx.domains.std import option_desc_re count = 0 @@ -187,13 +186,11 @@ def parse_django_adminopt_node(env, sig, signode): class DjangoStandaloneHTMLBuilder(StandaloneHTMLBuilder): - """ - Subclass to add some extra things we need. - """ + """Subclass to add some extra things we need.""" name = "djangohtml" - def finish(self): + def finish(self) -> None: super().finish() self.info(bold("writing templatebuiltins.js...")) xrefs = self.env.domaindata["std"]["objects"] @@ -201,12 +198,12 @@ def finish(self): "ttags": [ n for ((t, n), (l, a)) in xrefs.items() # noqa - if t == "templatetag" and l == "ref/templates/builtins" # noqa + if t == "templatetag" and l == "ref/templates/builtins" ], "tfilters": [ n for ((t, n), (l, a)) in xrefs.items() # noqa - if t == "templatefilter" and l == "ref/templates/builtins" # noqa + if t == "templatefilter" and l == "ref/templates/builtins" ], } outfilename = os.path.join(self.outdir, "templatebuiltins.js") diff --git a/docs/source/_ext/github.py b/docs/source/_ext/github.py index 184067ad..70cd0867 100644 --- a/docs/source/_ext/github.py +++ b/docs/source/_ext/github.py @@ -1,4 +1,5 @@ -"""Define text roles for GitHub +""" +Define text roles for GitHub. * ghissue - Issue * ghpull - Pull Request @@ -13,16 +14,19 @@ * Doug Hellmann * Min RK """ + # # Original Copyright (c) 2010 Doug Hellmann. All rights reserved. # +from __future__ import annotations from docutils import nodes, utils from docutils.parsers.rst.roles import set_classes def make_link_node(rawtext, app, type, slug, options): - """Create a link to a github resource. + """ + Create a link to a github resource. :param rawtext: Text being replaced with link node. :param app: Sphinx application context @@ -30,7 +34,6 @@ def make_link_node(rawtext, app, type, slug, options): :param slug: ID of the thing to link to :param options: Options dictionary passed to role func. """ - try: base = app.config.github_project_url if not base: @@ -38,19 +41,20 @@ def make_link_node(rawtext, app, type, slug, options): if not base.endswith("/"): base += "/" except AttributeError as err: - raise ValueError("github_project_url configuration value is not set (%s)" % str(err)) + msg = f"github_project_url configuration value is not set ({err!s})" + raise ValueError(msg) ref = base + type + "/" + slug + "/" set_classes(options) prefix = "#" if type == "pull": prefix = "PR " + prefix - node = nodes.reference(rawtext, prefix + utils.unescape(slug), refuri=ref, **options) - return node + return nodes.reference(rawtext, prefix + utils.unescape(slug), refuri=ref, **options) -def ghissue_role(name, rawtext, text, lineno, inliner, options={}, content=[]): - """Link to a GitHub issue. +def ghissue_role(name, rawtext, text, lineno, inliner, options=None, content=None): + """ + Link to a GitHub issue. Returns 2 part tuple containing list of nodes to insert into the document and a list of system messages. Both are allowed to be @@ -64,14 +68,17 @@ def ghissue_role(name, rawtext, text, lineno, inliner, options={}, content=[]): :param options: Directive options for customization. :param content: The directive content for customization. """ - + if content is None: + content = [] + if options is None: + options = {} try: issue_num = int(text) if issue_num <= 0: raise ValueError except ValueError: msg = inliner.reporter.error( - "GitHub issue number must be a number greater than or equal to 1; " '"%s" is invalid.' % text, + f'GitHub issue number must be a number greater than or equal to 1; "{text}" is invalid.', line=lineno, ) prb = inliner.problematic(rawtext, rawtext, msg) @@ -84,7 +91,7 @@ def ghissue_role(name, rawtext, text, lineno, inliner, options={}, content=[]): category = "issues" else: msg = inliner.reporter.error( - 'GitHub roles include "ghpull" and "ghissue", ' '"%s" is invalid.' % name, + f'GitHub roles include "ghpull" and "ghissue", "{name}" is invalid.', line=lineno, ) prb = inliner.problematic(rawtext, rawtext, msg) @@ -93,8 +100,9 @@ def ghissue_role(name, rawtext, text, lineno, inliner, options={}, content=[]): return [node], [] -def ghuser_role(name, rawtext, text, lineno, inliner, options={}, content=[]): - """Link to a GitHub user. +def ghuser_role(name, rawtext, text, lineno, inliner, options=None, content=None): + """ + Link to a GitHub user. Returns 2 part tuple containing list of nodes to insert into the document and a list of system messages. Both are allowed to be @@ -110,13 +118,18 @@ def ghuser_role(name, rawtext, text, lineno, inliner, options={}, content=[]): """ # app = inliner.document.settings.env.app # app.info('user link %r' % text) + if content is None: + content = [] + if options is None: + options = {} ref = "https://www.github.com/" + text node = nodes.reference(rawtext, text, refuri=ref, **options) return [node], [] -def ghcommit_role(name, rawtext, text, lineno, inliner, options={}, content=[]): - """Link to a GitHub commit. +def ghcommit_role(name, rawtext, text, lineno, inliner, options=None, content=None): + """ + Link to a GitHub commit. Returns 2 part tuple containing list of nodes to insert into the document and a list of system messages. Both are allowed to be @@ -130,6 +143,10 @@ def ghcommit_role(name, rawtext, text, lineno, inliner, options={}, content=[]): :param options: Directive options for customization. :param content: The directive content for customization. """ + if content is None: + content = [] + if options is None: + options = {} app = inliner.document.settings.env.app # app.info('user link %r' % text) try: @@ -139,15 +156,17 @@ def ghcommit_role(name, rawtext, text, lineno, inliner, options={}, content=[]): if not base.endswith("/"): base += "/" except AttributeError as err: - raise ValueError("github_project_url configuration value is not set (%s)" % str(err)) + msg = f"github_project_url configuration value is not set ({err!s})" + raise ValueError(msg) ref = base + text node = nodes.reference(rawtext, text[:6], refuri=ref, **options) return [node], [] -def setup(app): - """Install the plugin. +def setup(app) -> None: + """ + Install the plugin. :param app: Sphinx application context. """ @@ -156,4 +175,3 @@ def setup(app): app.add_role("ghuser", ghuser_role) app.add_role("ghcommit", ghcommit_role) app.add_config_value("github_project_url", None, "env") - return diff --git a/docs/source/_ext/version.py b/docs/source/_ext/version.py index 908ccddc..51b7d7d7 100644 --- a/docs/source/_ext/version.py +++ b/docs/source/_ext/version.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import re from sphinx import addnodes, roles @@ -6,7 +8,7 @@ simple_option_desc_re = re.compile(r"([-_a-zA-Z0-9]+)(\s*.*?)(?=,\s+(?:/|-|--)|$)") -def setup(app): +def setup(app) -> None: app.add_crossref_type( directivename="setting", rolename="setting", @@ -62,13 +64,13 @@ def run(self): link = None else: version = arg0 - link = "release-%s" % arg0 + link = f"release-{arg0}" node["version"] = version # inodes, messages = self.state.inline_text(self.version_text[self.name] % version, self.lineno+1) # node.extend(inodes) if link: - text = " Please see the changelog <%s>" % link + text = f" Please see the changelog <{link}>" xrefs = roles.XRefRole()("std:ref", text, text, self.lineno, self.state) node.extend(xrefs[0]) env.note_versionchange(node["type"], node["version"], node, self.lineno) diff --git a/docs/source/changes.rst b/docs/source/changes.rst index d88f0b7c..49a64b5d 100644 --- a/docs/source/changes.rst +++ b/docs/source/changes.rst @@ -14,4 +14,3 @@ This sections lists the biggest changes done on each release. :local: .. include:: ../../CHANGES - diff --git a/docs/source/conf.py b/docs/source/conf.py index 84b4d6fe..603bdd15 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -8,12 +8,18 @@ # # All configuration values have a default; values that are commented out # serve to show the default. +from __future__ import annotations import os import sys here = os.path.abspath(os.path.join(os.path.dirname(__file__))) -up = lambda base, level: os.path.abspath(os.path.join(base, *([os.pardir] * level))) + + +def up(base, level): + return os.path.abspath(os.path.join(base, *([os.pardir] * level))) + + sys.path.insert(0, up(here, 2)) from django.conf import settings diff --git a/docs/source/exceptions.rst b/docs/source/exceptions.rst index 1fd8a57a..b5e2a47e 100644 --- a/docs/source/exceptions.rst +++ b/docs/source/exceptions.rst @@ -10,4 +10,3 @@ Exceptions --------------------- Exception raised to interrupt an action. - diff --git a/docs/source/faq.rst b/docs/source/faq.rst index 97f9571c..cc6b0d29 100644 --- a/docs/source/faq.rst +++ b/docs/source/faq.rst @@ -95,6 +95,3 @@ here the partial code:: :func:`export_delete_tree` will dump only ``Rome`` :func:`export_as_fixture` will dump the whole tree - - - diff --git a/docs/source/howto.rst b/docs/source/howto.rst index 5f38f2fc..1ac746bc 100644 --- a/docs/source/howto.rst +++ b/docs/source/howto.rst @@ -92,4 +92,3 @@ Limit Massupdate hints to certain fields mass_update_hints = ['name'] admin.register(MyModel, MyModelAdmin) - diff --git a/docs/source/install.rst b/docs/source/install.rst index 8dc3cd0a..065ada09 100644 --- a/docs/source/install.rst +++ b/docs/source/install.rst @@ -68,7 +68,7 @@ Add defaults for the Export to CSV to the Django Config. See all available settings at :ref:`_export_as_csv`.:: import csv - + ADMINACTIONS_CSV_OPTIONS_DEFAULT = { 'date_format': 'Y-m-d', 'datetime_format': 'Y-m-d G:i:s O', diff --git a/docs/source/permissions.rst b/docs/source/permissions.rst index 3308d4ac..b5f38d2c 100644 --- a/docs/source/permissions.rst +++ b/docs/source/permissions.rst @@ -34,4 +34,3 @@ adminactions_merge ================== Required to execute :ref:`merge` - diff --git a/manage.py b/manage.py index 259b26f0..badc1fb0 100755 --- a/manage.py +++ b/manage.py @@ -1,9 +1,15 @@ #!/usr/bin/env python +from __future__ import annotations + import os import sys here = os.path.abspath(os.path.join(os.path.dirname(__file__))) -rel = lambda *args: os.path.join(here, *args) + + +def rel(*args): + return os.path.join(here, *args) + sys.path.insert(0, rel(os.pardir)) sys.path.insert(0, rel("src")) diff --git a/pyproject.toml b/pyproject.toml index 0417f724..ef734259 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,11 +1,140 @@ -[tool.black] -line-length = 110 -target-version = ['py39'] +[project] +name = "django-adminactions" +version = "2.3.0" +description = "Collections of useful actions to use with django.contrib.admin.ModelAdmin" +readme = "README.md" +license = { text = "MIT" } +authors = [ + { name = "sax", email = "s.apostolico@gmail.com" }, +] +requires-python = ">=3.11.0" +classifiers = [ + "Environment :: Web Environment", + "Framework :: Django", + "Framework :: Django :: 3.2", + "Framework :: Django :: 4.2", + "Framework :: Django :: 5.0", + "Intended Audience :: Developers", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", +] +dependencies = [ + "pytz", + "xlrd>=0.9.2", + "xlwt", +] +optional-dependencies.dev = [ +] +urls.Downloads = "https://github.com/saxix/django-adminactions" +urls.Homepage = "https://github.com/saxix/django-adminactions" -[tool.isort] -profile = "black" -line_length = 110 -lines_between_sections = 1 -known_first_party = "adminactions" -skip = "migrations" +[dependency-groups] +dev = [ + "black>=25.1", + "celery>=5.4", + "check-manifest>=0.50", + "django-admin-extra-urls>=4.1.1", + "django-dynamic-fixture>=4.0.1", + "django-environ>=0.12", + "django-webtest>1.9.6", + "mock>=1.0.1", + "modernize>=0.8", + "mypy>=1.15", + "pillow>=11.1", + "psycopg2>=2.9.10", + "pytest>=8.3.4", + "pytest-cache>=1", + "pytest-cov>=6", + "pytest-django>=4.9", + "pytest-echo>=1.8.1", + "readme>=0.7.1", + "redis>=5.2.1", + "ruff>=0.9.4", + "selenium>=2.42", + "setuptools>=15", + "tox>=4.2", +] + +[tool.ruff] +target-version = "py311" +line-length = 120 +format.preview = true +format.docstring-code-line-length = 100 +format.docstring-code-format = true +lint.select = [ + "ALL", +] +lint.ignore = [ + # "A", + # "ANN", + "ANN401", + "ARG", + "B", + "BLE", + "C", + "COM", + "CPY", + "D", + "DOC", + "DTZ", + "E", + "EM", + "ERA", + "F", + "FBT", + "FURB", + "N", + "PERF", + "PGH", + "PLC", + "PLR", + "PLW", + "RET", + "RUF", + "S", + "SIM", + "SLF", + "TRY", + "UP", + +] +lint.per-file-ignores."docs/conf.py" = [ + "A001", # + "D100", # + "ERA001", # + "INP001", # +] +lint.per-file-ignores."tests/**/*.py" = [ + "D", # don"t care about documentation in tests + "FBT", # don"t care about booleans as positional arguments in tests + "INP001", # no implicit namespace + "PLR2004", # Magic value used in comparison, consider replacing with a constant variable + "S101", # asserts allowed in tests... + "S603", # `subprocess` call: check for execution of untrusted input +] +lint.isort = { known-first-party = [ "pytest_echo" ] } + +lint.preview = true + +[tool.pyproject-fmt] +max_supported_python = "3.13" + +[tool.pytest.ini_options] +django_find_project = false +norecursedirs = [ "demo", ".tox" ] +addopts = "--doctest-modules --tb=short --reuse-db --cov=adminactions --cov-report=html --cov-config=tests/.coveragerc --capture=no --doctest-glob=adminactions/*.py" +echo-version = [ "django" ] + +python_files = "tests/test_*.py tests/**/test_*.py" +markers = [ + "functional: mark a test as functional", + "selenium: selenium test", + "skip: skip test", +] + +[tool.uv] +package = true diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 529e5e97..00000000 --- a/setup.cfg +++ /dev/null @@ -1,43 +0,0 @@ -[isort] -combine_as_imports = true -default_section = THIRDPARTY -include_trailing_comma = true -line_length=80 -known_third_party = django -known_first_party = adminactions,demo -multi_line_output = 0 -sections=FUTURE,STDLIB,THIRDPARTY,FIRSTPARTY,LOCALFOLDER - -[wheel] -universal = 1 - -[egg_info] -tag_build = -tag_date = 0 -tag_svn_revision = 0 - -[devpi:upload] -formats=bdist_wheel,sdist.tgz - -[pylama] -format = pylint -skip = */.tox/*,*/.env/* -linters = pylint,mccabe -ignore = F0401,C0111,E731 - - -[flake8] -# File filtering is taken care of in pre-commit. -# E203 false positive, see https://github.com/PyCQA/pycodestyle/issues/373 -# B011 We don't use PYTHONOPTIMIZE. - -# XXX: E501 is ignored, which disables line length checking. -# Currently, the black formatter doesn't wrap long strings: https://github.com/psf/black/issues/182#issuecomment-385325274 -# We already have a lot of E501's - these are lines black didn't wrap. -# But rather than append # noqa: E501 to all of them, we just ignore E501 for now. -extend-ignore = E203,E501,E402,E731,B007,B009,B010,B011,B020,B023,B024,B026,B027 - -per-file-ignores = - # these scripts must have minimal dependencies so opt out of the usual sentry rules - tools/*: S - .github/*: S diff --git a/setup.py b/setup.py deleted file mode 100755 index 075db12a..00000000 --- a/setup.py +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/env python -import ast -import codecs -import os -import re - -from setuptools import find_packages, setup - -ROOT = os.path.realpath(os.path.join(os.path.dirname(__file__))) -init = os.path.join(ROOT, "src", "adminactions", "__init__.py") - - -def read(*parts): - with codecs.open(os.path.join(ROOT, "src", "requirements", *parts), "r") as fp: - return fp.read() - - -_version_re = re.compile(r"__version__\s+=\s+(.*)") - -with open(init, "rb") as f: - version = str(ast.literal_eval(_version_re.search(f.read().decode("utf-8")).group(1))) - -requirements = read("install.pip") -tests_require = read("testing.pip") -dev_require = read("develop.pip") -docs_require = read("rtd.pip") - -setup( - name="django-adminactions", - version=version, - url="https://github.com/saxix/django-adminactions", - download_url="https://github.com/saxix/django-adminactions", - author="sax", - author_email="s.apostolico@gmail.com", - description="Collections of useful actions to use with django.contrib.admin.ModelAdmin", - license="MIT", - package_dir={"": "src"}, - packages=find_packages("src"), - include_package_data=True, - install_requires=requirements, - tests_require=tests_require, - extras_require={ - "test": requirements + tests_require, - "dev": dev_require + tests_require, - "docs": dev_require + docs_require, - }, - zip_safe=False, - platforms=["any"], - classifiers=[ - "Environment :: Web Environment", - "Framework :: Django", - "Operating System :: OS Independent", - "Framework :: Django :: 2.2", - "Framework :: Django :: 3.2", - "Framework :: Django :: 4.0", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Intended Audience :: Developers", - ], - long_description=open("README.md").read(), - long_description_content_type="text/markdown", -) diff --git a/src/adminactions/actions.py b/src/adminactions/actions.py index 7e232376..b35df6c6 100644 --- a/src/adminactions/actions.py +++ b/src/adminactions/actions.py @@ -1,3 +1,7 @@ +from typing import Optional + +from django.contrib.admin import AdminSite + from .bulk_update import bulk_update from .byrows_update import byrows_update from .duplicates import find_duplicates_action @@ -20,7 +24,7 @@ ] -def add_to_site(site, exclude=None, include=None): +def add_to_site(site: AdminSite, exclude: Optional[list[str]] = None, include: Optional[list[str]] = None) -> None: """ Register all the adminactions into passed site @@ -37,7 +41,7 @@ def add_to_site(site, exclude=None, include=None): >>> add_to_site(site) >>> from django.contrib.admin import site - >>> add_to_site(site, exclude=['merge']) + >>> add_to_site(site, exclude=["merge"]) """ exclude = exclude or [] diff --git a/src/adminactions/api.py b/src/adminactions/api.py index d4c1ea23..124c7e7d 100644 --- a/src/adminactions/api.py +++ b/src/adminactions/api.py @@ -1,13 +1,16 @@ +from __future__ import annotations + import collections import csv import datetime import itertools from io import BytesIO +from typing import TYPE_CHECKING, Any, Generator import xlwt from django.conf import settings from django.core.exceptions import FieldDoesNotExist, ObjectDoesNotExist -from django.db.models import FileField +from django.db.models import FileField, Model from django.db.models.fields.related import ManyToManyField, OneToOneField from django.db.transaction import atomic from django.http import HttpResponse, StreamingHttpResponse @@ -19,6 +22,15 @@ from .utils import clone_instance, get_field_by_path, get_field_value, get_ignored_fields +if TYPE_CHECKING: + from collections.abc import Iterable + + from django.contrib.admin.options import ModelAdmin + from django.core.files.base import File + from django.db.models.query import QuerySet + + from .forms import CSVOptions, XLSOptions + csv_options_default = { "date_format": "d/m/Y", "datetime_format": "N j, Y, P", @@ -36,7 +48,14 @@ ALL_FIELDS = -999 -def merge(master, other, fields=None, commit=False, m2m=None, related=None): # noqa +def merge( + master: Model, + other: Model, + fields: Iterable[str] | None = None, + commit: bool = False, + m2m: Iterable[str] | None = None, + related: Iterable[str] | None = None, +) -> Model: """ Merge 'other' into master. @@ -62,10 +81,10 @@ def merge(master, other, fields=None, commit=False, m2m=None, related=None): # if m2m == ALL_FIELDS: m2m = set() - for field in master._meta.get_fields(): + for field in master._meta.get_fields(): # noqa: SLF001 if getattr(field, "many_to_many", None): if isinstance(field, ManyToManyField): - if not field.remote_field.through._meta.auto_created: + if not field.remote_field.through._meta.auto_created: # noqa: SLF001 continue m2m.add(field.name) else: @@ -109,9 +128,9 @@ def merge(master, other, fields=None, commit=False, m2m=None, related=None): # setattr(element, rel_fieldname, master) element.save() other.delete() - ignored_fields = get_ignored_fields(result._meta.model, "MERGE_ACTION_IGNORED_FIELDS") + ignored_fields = get_ignored_fields(result._meta.model, "MERGE_ACTION_IGNORED_FIELDS") # noqa: SLF001 for ig_field in ignored_fields: - setattr(result, ig_field, result._meta.get_field(ig_field).get_default()) + setattr(result, ig_field, result._meta.get_field(ig_field).get_default()) # noqa: SLF001 result.save() for fieldname, elements in list(all_m2m.items()): dest_m2m = getattr(result, fieldname) @@ -125,20 +144,20 @@ class Echo: interface. """ - def write(self, value): + def write(self, value: Any) -> Any: """Write the value by returning it, instead of storing in a buffer.""" return value -def export_as_csv( # noqa: max-complexity: 20 - queryset, - fields=None, - header=None, - filename=None, - options=None, - out=None, - modeladmin=None, -): # noqa +def export_as_csv( + queryset: QuerySet, + fields: list[str] | None = None, + header: bool = False, + filename: str | None = None, + options: CSVOptions | None = None, + out: File | None = None, + modeladmin: ModelAdmin = None, +) -> HttpResponse: """ Exports a queryset as csv from a queryset with the given fields. @@ -162,9 +181,7 @@ def export_as_csv( # noqa: max-complexity: 20 filename = "%s.csv" % queryset.model._meta.verbose_name_plural.lower().replace(" ", "_") response = response_class(content_type="text/csv") - response["Content-Disposition"] = ('attachment;filename="%s"' % filename).encode( - "us-ascii", "replace" - ) + response["Content-Disposition"] = ('attachment;filename="%s"' % filename).encode("us-ascii", "replace") else: response = out @@ -194,7 +211,7 @@ def export_as_csv( # noqa: max-complexity: 20 settingstime_zone = get_default_timezone() - def yield_header(): + def yield_header() -> Generator[str, None, None]: if bool(header): if isinstance(header, (list, tuple)): yield writer.writerow(header) @@ -202,7 +219,7 @@ def yield_header(): yield writer.writerow([f for f in fields]) yield "" - def yield_rows(): + def yield_rows() -> Generator[str, None, None]: for obj in queryset: row = [] for fieldname in fields: @@ -253,9 +270,15 @@ def yield_rows(): } -def export_as_xls2( # noqa: max-complexity: 24 - queryset, fields=None, header=None, filename=None, options=None, out=None, modeladmin=None # noqa -): +def export_as_xls2( + queryset: "QuerySet", + fields: list[str] = None, + header: bool = False, + filename: str | None = None, + options: "XLSOptions" | None = None, + out: File | None = None, + modeladmin: ModelAdmin | None = None, # noqa +) -> HttpResponse: # sheet_name=None, header_alt=None, # formatting=None, out=None): """ @@ -270,7 +293,7 @@ def export_as_xls2( # noqa: max-complexity: 24 :return: HttpResponse instance if out not supplied, otherwise out """ - def _get_qs_formats(queryset): + def _get_qs_formats(queryset: "QuerySet") -> HttpResponse: formats = {} if hasattr(queryset, "model"): for i, fieldname in enumerate(fields): @@ -281,9 +304,7 @@ def _get_qs_formats(queryset): __, __, ) = utils.get_field_by_name(queryset.model, fieldname) - fmt = xls_options_default.get( - f.name, xls_options_default.get(f.__class__.__name__, "general") - ) + fmt = xls_options_default.get(f.name, xls_options_default.get(f.__class__.__name__, "general")) formats[i] = fmt except FieldDoesNotExist: pass @@ -295,9 +316,7 @@ def _get_qs_formats(queryset): filename = "%s.xls" % queryset.model._meta.verbose_name_plural.lower().replace(" ", "_") response = HttpResponse(content_type="application/vnd.ms-excel") - response["Content-Disposition"] = ('attachment;filename="%s"' % filename).encode( - "us-ascii", "replace" - ) + response["Content-Disposition"] = ('attachment;filename="%s"' % filename).encode("us-ascii", "replace") else: response = out @@ -306,7 +325,7 @@ def _get_qs_formats(queryset): config.update(options) if fields is None: - fields = [f.name for f in queryset.model._meta.fields + queryset.model._meta.many_to_many] + fields = [f.name for f in queryset.model._meta.fields + queryset.model._meta.many_to_many] # noqa: SLF001 book = xlwt.Workbook(encoding="utf-8", style_compression=2) sheet_name = config.pop("sheet_name") @@ -321,7 +340,7 @@ def _get_qs_formats(queryset): if not isinstance(header, (list, tuple)): header = [ force_str(f.verbose_name) - for f in queryset.model._meta.fields + queryset.model._meta.many_to_many + for f in queryset.model._meta.fields + queryset.model._meta.many_to_many # noqa: SLF001 if f.name in fields ] @@ -332,7 +351,7 @@ def _get_qs_formats(queryset): sheet.row(row).height = 500 formats = _get_qs_formats(queryset) - _styles = {} + styles_ = {} for rownum, row in enumerate(queryset): sheet.write(rownum + 1, 0, rownum + 1) @@ -344,24 +363,24 @@ def _get_qs_formats(queryset): ) if callable(fmt): value = xlwt.Formula(fmt(value)) - if hash(fmt) not in _styles: + if hash(fmt) not in styles_: if callable(fmt): - _styles[hash(fmt)] = xlwt.easyxf(num_format_str="formula") + styles_[hash(fmt)] = xlwt.easyxf(num_format_str="formula") elif isinstance(value, datetime.datetime): - _styles[hash(fmt)] = xlwt.easyxf(num_format_str=config["datetime_format"]) + styles_[hash(fmt)] = xlwt.easyxf(num_format_str=config["datetime_format"]) elif isinstance(value, datetime.date): - _styles[hash(fmt)] = xlwt.easyxf(num_format_str=config["date_format"]) + styles_[hash(fmt)] = xlwt.easyxf(num_format_str=config["date_format"]) elif isinstance(value, datetime.datetime): - _styles[hash(fmt)] = xlwt.easyxf(num_format_str=config["time_format"]) + styles_[hash(fmt)] = xlwt.easyxf(num_format_str=config["time_format"]) else: - _styles[hash(fmt)] = xlwt.easyxf(num_format_str=fmt) + styles_[hash(fmt)] = xlwt.easyxf(num_format_str=fmt) if isinstance(value, (list, tuple)): value = "".join(value) - sheet.write(rownum + 1, col_idx + 1, value, _styles[hash(fmt)]) + sheet.write(rownum + 1, col_idx + 1, value, styles_[hash(fmt)]) except Exception as e: - sheet.write(rownum + 1, col_idx + 1, smart_str(e), _styles[hash(fmt)]) + sheet.write(rownum + 1, col_idx + 1, smart_str(e), styles_[hash(fmt)]) book.save(response) return response @@ -388,9 +407,15 @@ def _get_qs_formats(queryset): } -def export_as_xls3( # noqa: max-complexity: 23 - queryset, fields=None, header=None, filename=None, options=None, out=None, modeladmin=None # noqa -): # pragma: no cover +def export_as_xls3( + queryset: "QuerySet", + fields: list[str] | None = None, + header: bool = False, + filename: str | None = None, + options: "XLSOptions | None" = None, + out: File | None = None, + modeladmin: ModelAdmin | None = None, # noqa +) -> HttpResponse: # pragma: no cover # sheet_name=None, header_alt=None, # formatting=None, out=None): """ @@ -406,7 +431,7 @@ def export_as_xls3( # noqa: max-complexity: 23 """ import xlsxwriter - def _get_qs_formats(queryset): + def _get_qs_formats(queryset: "QuerySet") -> HttpResponse: formats = {"_general_": book.add_format()} if hasattr(queryset, "model"): for i, fieldname in enumerate(fields): @@ -416,10 +441,8 @@ def _get_qs_formats(queryset): __, __, __, - ) = queryset.model._meta.get_field_by_name(fieldname) - pattern = xlsxwriter_options.get( - f.name, xlsxwriter_options.get(f.__class__.__name__, "general") - ) + ) = queryset.model._meta.get_field_by_name(fieldname) # noqa: SLF001 + pattern = xlsxwriter_options.get(f.name, xlsxwriter_options.get(f.__class__.__name__, "general")) fmt = book.add_format({"num_format": pattern}) formats[fieldname] = fmt except FieldDoesNotExist: @@ -435,7 +458,7 @@ def _get_qs_formats(queryset): config.update(options) if fields is None: - fields = [f.name for f in queryset.model._meta.fields + queryset.model._meta.many_to_many] + fields = [f.name for f in queryset.model._meta.fields + queryset.model._meta.many_to_many] # noqa: SLF001 book = xlsxwriter.Workbook(out, {"in_memory": True}) sheet_name = config.pop("sheet_name") @@ -450,7 +473,7 @@ def _get_qs_formats(queryset): if not isinstance(header, (list, tuple)): header = [ force_str(f.verbose_name) - for f in queryset.model._meta.fields + queryset.model._meta.many_to_many + for f in queryset.model._meta.fields + queryset.model._meta.many_to_many # noqa: SLF001 if f.name in fields ] @@ -491,7 +514,7 @@ def _get_qs_formats(queryset): out.seek(0) if http_response: if filename is None: - filename = "%s.xls" % queryset.model._meta.verbose_name_plural.lower().replace(" ", "_") + filename = "%s.xls" % queryset.model._meta.verbose_name_plural.lower().replace(" ", "_") # noqa: SLF001 response = HttpResponse( out.read(), content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", diff --git a/src/adminactions/apps.py b/src/adminactions/apps.py index fb9b6f5e..20eca9d6 100644 --- a/src/adminactions/apps.py +++ b/src/adminactions/apps.py @@ -6,7 +6,7 @@ class Config(AppConfig): name = "adminactions" - def ready(self): + def ready(self) -> None: from adminactions import consts from . import checks # noqa diff --git a/src/adminactions/bulk_update.py b/src/adminactions/bulk_update.py index 2aef6d58..6b974345 100644 --- a/src/adminactions/bulk_update.py +++ b/src/adminactions/bulk_update.py @@ -1,8 +1,10 @@ +from __future__ import annotations + import codecs import csv import logging from pathlib import Path -from typing import Dict, Optional, Sequence +from typing import TYPE_CHECKING, Any, Dict, Optional, Sequence from django import forms from django.contrib import messages @@ -14,6 +16,7 @@ from django.db.transaction import atomic from django.forms import Media from django.http import HttpResponseRedirect +from django.http.request import HttpRequest from django.shortcuts import render from django.utils.encoding import smart_str from django.utils.safestring import mark_safe @@ -24,6 +27,13 @@ from adminactions.perms import get_permission_codename from adminactions.signals import adminaction_end, adminaction_requested, adminaction_start +if TYPE_CHECKING: + from django.contrib.admin import ModelAdmin + from django.db.models import QuerySet + from django.db.models.fields import Field + from django.http.request import HttpRequest + from django.http.response import HttpResponse + logger = logging.getLogger(__name__) @@ -56,7 +66,7 @@ class BulkUpdateForm(forms.Form): ) @property - def media(self): + def media(self) -> Media: """Return all media required to render the widgets on this form.""" media = Media( js=["adminactions/js/bulkupdate.js"], @@ -70,7 +80,7 @@ def media(self): class BulkUpdateMappingForm(forms.Form): index_field = forms.MultipleChoiceField(choices=[], widget=forms.CheckboxSelectMultiple) - def __init__(self, *args, **kwargs): + def __init__(self, *args: Any, **kwargs: Any) -> None: self.model = kwargs.pop("model") super().__init__(*args, **kwargs) # self._errors = None @@ -83,7 +93,7 @@ def __init__(self, *args, **kwargs): # self.initial[f[0]] = f[0] # self.fields[f[0]].widget.initial = f[0] - def _clean_fields(self): + def _clean_fields(self) -> None: for name, field in self.fields.items(): value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name)) self.cleaned_data[name] = value @@ -93,10 +103,10 @@ def _clean_fields(self): ValidationError(_("Please select one or more index fields")), ) - def _post_clean(self): + def _post_clean(self) -> None: pass - def get_mapping(self): + def get_mapping(self) -> dict[str, str]: mapping = self.cleaned_data.copy() mapping.pop("index_field") return {k: v for k, v in mapping.items() if v.strip()} @@ -146,9 +156,7 @@ def bulk_update(modeladmin, request, queryset): # noqa if "apply" in request.POST: form = bulk_update_form(request.POST, request.FILES, initial=form_initial) csv_form = CSVConfigForm(request.POST, initial=csv_initial, prefix="csv") - map_form = BulkUpdateMappingForm( - request.POST, initial=map_initial, model=modeladmin.model, prefix="fld" - ) + map_form = BulkUpdateMappingForm(request.POST, initial=map_initial, model=modeladmin.model, prefix="fld") if form.is_valid() and csv_form.is_valid() and map_form.is_valid(): header = csv_form.cleaned_data.pop("header") @@ -233,18 +241,18 @@ def bulk_update(modeladmin, request, queryset): # noqa bulk_update.base_permission = "adminactions_bulkupdate" -def _bulk_update( # noqa: max-complexity: 18 - queryset, - file_name_or_object, +def _bulk_update( + queryset: "QuerySet", + file_name_or_object: str | Field, *, - mapping: Dict, + mapping: dict, indexes: Sequence[str], - clean=False, + clean: bool = False, header: bool = True, csv_options: Optional[Dict] = None, - request=None, + request: HttpRequest | None = None, dry_run: bool = False, -): +) -> dict[str, list[str]]: results = { "updated": [], "errors": [], @@ -281,9 +289,7 @@ def _bulk_update( # noqa: max-complexity: 18 model_field = queryset.model._meta.get_field(field) if model_field.is_relation and model_field.many_to_one: related_model = model_field.related_model - related_field_name = ( - model_field.to_fields[0] if model_field.to_fields else "pk" - ) + related_field_name = model_field.to_fields[0] if model_field.to_fields else "pk" related_field = related_model._meta.get_field(related_field_name) if isinstance(related_field, models.UUIDField): diff --git a/src/adminactions/byrows_update.py b/src/adminactions/byrows_update.py index 6ae65100..1cb32c7f 100644 --- a/src/adminactions/byrows_update.py +++ b/src/adminactions/byrows_update.py @@ -1,5 +1,10 @@ +from typing import Any + +from django import forms from django.contrib import messages from django.contrib.admin import helpers +from django.contrib.admin.options import ModelAdmin +from django.db.models import fields as django_fields from django.forms.models import modelform_factory, modelformset_factory from django.http import HttpResponseRedirect from django.shortcuts import render @@ -30,12 +35,10 @@ def byrows_update(modeladmin, request, queryset): # noqa return class modelform(modeladmin.form): - def __init__(self, *args, **kwargs): + def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) if self.instance: - readonly_fields = (modeladmin.model._meta.pk.name,) + tuple( - modeladmin.get_readonly_fields(request) - ) + readonly_fields = (modeladmin.model._meta.pk.name,) + tuple(modeladmin.get_readonly_fields(request)) for fname in readonly_fields: if fname in self.fields: self.fields[fname].widget.attrs["readonly"] = "readonly" @@ -43,7 +46,7 @@ def __init__(self, *args, **kwargs): fields = byrows_update_get_fields(modeladmin) - def formfield_callback(field, **kwargs): + def formfield_callback(field: django_fields.Field, **kwargs: Any) -> forms.Field: return modeladmin.formfield_for_dbfield(field, request=request, **kwargs) ActionForm = modelform_factory( @@ -77,9 +80,7 @@ def formfield_callback(field, **kwargs): actionform = ActionForm(initial=action_form_initial, instance=None) formset = MFormSet(queryset=queryset) - adminform = helpers.AdminForm( - actionform, modeladmin.get_fieldsets(request), {}, [], model_admin=modeladmin - ) + adminform = helpers.AdminForm(actionform, modeladmin.get_fieldsets(request), {}, [], model_admin=modeladmin) tpl = "adminactions/byrows_update.html" ctx = { @@ -103,7 +104,7 @@ def formfield_callback(field, **kwargs): byrows_update.base_permission = "adminactions_byrowsupdate" -def byrows_update_get_fields(modeladmin): +def byrows_update_get_fields(modeladmin: ModelAdmin) -> list[str]: """ Get fields names to be shown of the model rows formset considering the admin option: diff --git a/src/adminactions/checks.py b/src/adminactions/checks.py index 5eb7e7d6..04ad8216 100644 --- a/src/adminactions/checks.py +++ b/src/adminactions/checks.py @@ -1,8 +1,11 @@ +from typing import Any + +from django.apps.config import AppConfig from django.core.checks import Error, register @register() -def check_adminactions_settings(app_configs, **kwargs): +def check_adminactions_settings(app_configs: AppConfig, **kwargs: Any) -> None: errors = [] from .config import AA_PERMISSION_HANDLER from .consts import ( diff --git a/src/adminactions/duplicates.py b/src/adminactions/duplicates.py index bd2d8fc6..5c5a556d 100644 --- a/src/adminactions/duplicates.py +++ b/src/adminactions/duplicates.py @@ -1,3 +1,7 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING, Any + from django import forms from django.contrib import messages from django.contrib.admin import helpers @@ -11,6 +15,13 @@ from adminactions.signals import adminaction_end, adminaction_requested, adminaction_start from adminactions.utils import get_common_context +if TYPE_CHECKING: + from django.contrib.admin import ModelAdmin + from django.db.models import QuerySet + from django.db.models.fields import Field + from django.http.request import HttpRequest + from django.http.response import HttpResponse + class DuplicatesForm(forms.Form): _selected_action = forms.CharField(widget=forms.MultipleHiddenInput) @@ -24,7 +35,7 @@ class DuplicatesForm(forms.Form): min = forms.IntegerField(required=True, initial=2) max = forms.IntegerField(required=False) - def __init__(self, *args, **kwargs): + def __init__(self, *args: Any, **kwargs: Any) -> None: self.model = kwargs.pop("model") self.field_names = [] super().__init__(*args, **kwargs) @@ -35,14 +46,14 @@ def __init__(self, *args, **kwargs): self.field_names.append(field.name) self.fields[field.name] = forms.BooleanField(label=label, required=False) - def clean(self): + def clean(self) -> dict[str, Any]: checked = [fname for fname in self.field_names if self.cleaned_data[fname]] if not checked: raise ValidationError("Select at least one field") return self.cleaned_data @property - def media(self): + def media(self) -> forms.Media: return super().media + forms.Media( css={ "screen": ("adminactions/css/adminactions.css",), @@ -50,7 +61,9 @@ def media(self): ) -def find_duplicates(qs, fields, min_dupe=1, max_dupe=None): +def find_duplicates( + qs: "QuerySet", fields: "list[Field]", min_dupe: int = 1, max_dupe: int | None = None +) -> "QuerySet": qs = qs.order_by() qs = qs.values(*fields) qs = qs.annotate(count_id=Count("id")) @@ -60,7 +73,7 @@ def find_duplicates(qs, fields, min_dupe=1, max_dupe=None): return qs -def find_duplicates_action(modeladmin, request, queryset): +def find_duplicates_action(modeladmin: "ModelAdmin", request: "HttpRequest", queryset: "QuerySet") -> "HttpResponse": opts = modeladmin.model._meta perm = "{0}.{1}".format( opts.app_label, diff --git a/src/adminactions/export.py b/src/adminactions/export.py index 4eaca560..bc56a7cb 100644 --- a/src/adminactions/export.py +++ b/src/adminactions/export.py @@ -1,5 +1,6 @@ import logging from itertools import chain +from typing import TYPE_CHECKING, Any from django.conf import settings from django.contrib import messages @@ -7,8 +8,12 @@ from django.core import serializers as ser from django.db import router from django.db.models import ForeignKey, ManyToManyField +from django.db.models.base import Model from django.db.models.deletion import Collector +from django.db.models.query import QuerySet +from django.forms.forms import Form from django.http import HttpResponse, HttpResponseRedirect +from django.http.request import HttpRequest from django.shortcuts import render from django.utils.safestring import mark_safe from django.utils.translation import gettext_lazy as _ @@ -20,10 +25,13 @@ from .perms import get_permission_codename from .signals import adminaction_end, adminaction_requested, adminaction_start +if TYPE_CHECKING: + from django.contrib.admin import ModelAdmin + logger = logging.getLogger(__name__) -def get_action(request): +def get_action(request: HttpRequest) -> list[str]: try: action_index = int(request.POST.get("index", 0)) except ValueError: @@ -32,16 +40,16 @@ def get_action(request): def base_export( - modeladmin, - request, - queryset, - title, - impl, # noqa - name, - action_short_description, - template, - form_class, -): + modeladmin: "ModelAdmin", + request: "HttpRequest", + queryset: QuerySet, + title: str, + impl: callable, # noqa + name: str, + action_short_description: str, + template: str, + form_class: type[Form], +) -> "HttpResponse": """ export a queryset to csv file """ @@ -65,9 +73,7 @@ def base_export( if hasattr(modeladmin, "get_exportable_columns"): cols = modeladmin.get_exportable_columns(request, form_class) else: - cols = [ - (f.name, f.verbose_name) for f in queryset.model._meta.fields + queryset.model._meta.many_to_many - ] + cols = [(f.name, f.verbose_name) for f in queryset.model._meta.fields + queryset.model._meta.many_to_many] initial = { "_selected_action": request.POST.getlist(helpers.ACTION_CHECKBOX_NAME), "select_across": request.POST.get("select_across") == "1", @@ -149,7 +155,7 @@ def base_export( base_export.base_permission = "adminactions_export" -def export_as_csv(modeladmin, request, queryset): +def export_as_csv(modeladmin: "ModelAdmin", request: HttpRequest, queryset: QuerySet) -> HttpResponse: if hasattr(modeladmin, "get_aa_export_form"): form_class = modeladmin.get_aa_export_form(request, "csv") or CSVOptions else: @@ -175,7 +181,7 @@ def export_as_csv(modeladmin, request, queryset): export_as_csv.base_permission = "adminactions_export" -def export_as_xls(modeladmin, request, queryset): +def export_as_xls(modeladmin: "ModelAdmin", request: HttpRequest, queryset: QuerySet) -> HttpResponse: if hasattr(modeladmin, "get_aa_export_form"): form_class = modeladmin.get_aa_export_form(request, "xls") or XLSOptions else: @@ -202,21 +208,21 @@ def export_as_xls(modeladmin, request, queryset): class FlatCollector: - def __init__(self, using): + def __init__(self, using: str) -> None: self._visited = [] super().__init__() - def collect(self, objs): + def collect(self, objs: list[Model]) -> None: self.data = objs self.models = set([o.__class__ for o in self.data]) class ForeignKeysCollector: - def __init__(self, using): + def __init__(self, using: str) -> None: self._visited = [] super().__init__() - def _collect(self, objs): + def _collect(self, objs: list[Model]) -> None: objects = [] for obj in objs: if obj and obj not in self._visited: @@ -235,16 +241,16 @@ def _collect(self, objs): objects.extend(self._collect([target])) return objects - def collect(self, objs): + def collect(self, objs: list[Model]) -> None: self._visited = [] self.data = self._collect(objs) self.models = set([o.__class__ for o in self.data]) - def __str__(self): + def __str__(self) -> str: return mark_safe(self.data) -def _dump_qs(form, queryset, data, filename): +def _dump_qs(form: Form, queryset: QuerySet, data: dict[str, Any], filename: str) -> None: fmt = form.cleaned_data.get("serializer") json = ser.get_serializer(fmt)() @@ -261,14 +267,12 @@ def _dump_qs(form, queryset, data, filename): queryset.model._meta.verbose_name_plural.lower().replace(" ", "_"), fmt, ) - response["Content-Disposition"] = ('attachment;filename="%s"' % filename).encode( - "us-ascii", "replace" - ) + response["Content-Disposition"] = ('attachment;filename="%s"' % filename).encode("us-ascii", "replace") response.content = ret return response -def export_as_fixture(modeladmin, request, queryset): +def export_as_fixture(modeladmin: "ModelAdmin", request: HttpRequest, queryset: QuerySet) -> "HttpResponse": initial = { "_selected_action": request.POST.getlist(helpers.ACTION_CHECKBOX_NAME), "select_across": request.POST.get("select_across") == "1", @@ -314,9 +318,7 @@ def export_as_fixture(modeladmin, request, queryset): messages.error(request, str(e)) return try: - _collector = ( - ForeignKeysCollector if form.cleaned_data.get("add_foreign_keys") else FlatCollector - ) + _collector = ForeignKeysCollector if form.cleaned_data.get("add_foreign_keys") else FlatCollector c = _collector(None) c.collect(queryset) adminaction_end.send( @@ -369,7 +371,7 @@ def export_as_fixture(modeladmin, request, queryset): export_as_fixture.base_permission = "adminactions_export" -def export_delete_tree(modeladmin, request, queryset): # noqa +def export_delete_tree(modeladmin: "ModelAdmin", request: HttpRequest, queryset: QuerySet) -> "HttpResponse": # noqa """ Export as fixture selected queryset and all the records that belong to. That mean that dump what will be deleted if the queryset was deleted diff --git a/src/adminactions/forms.py b/src/adminactions/forms.py index ee475c67..a98d15d0 100644 --- a/src/adminactions/forms.py +++ b/src/adminactions/forms.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import csv from django import forms @@ -22,11 +24,11 @@ class GenericActionForm(ModelForm): ) action = forms.CharField(label="", required=True, initial="", widget=forms.HiddenInput()) - def configured_fields(self): + def configured_fields(self) -> list[forms.Field]: return [field for field in self if not field.is_hidden and field.name.startswith("_")] @cached_property - def model_field_names(self): + def model_field_names(self) -> list[str]: ignored_fields = { "select_accross", "action", @@ -34,16 +36,14 @@ def model_field_names(self): } return [f.name for f in self._meta.model._meta.get_fields() if f.name not in ignored_fields] - def model_fields(self): + def model_fields(self) -> list[forms.Field]: # field_names = [f.name for f in self._meta.model._meta.get_fields() if f.name not in self.model_field_names] return [field for field in self if field.name in self.model_field_names] class CSVConfigForm(forms.Form): header = forms.BooleanField(label=_("Header"), required=False) - delimiter = forms.ChoiceField( - label=_("Delimiter"), choices=list(zip(delimiters, delimiters)), initial="," - ) + delimiter = forms.ChoiceField(label=_("Delimiter"), choices=list(zip(delimiters, delimiters)), initial=",") quotechar = forms.ChoiceField(label=_("Quotechar"), choices=list(zip(quotes, quotes)), initial="'") quoting = forms.TypedChoiceField( coerce=int, @@ -59,10 +59,10 @@ class CSVConfigForm(forms.Form): escapechar = forms.ChoiceField(label=_("Escapechar"), choices=(("", ""), ("\\", "\\")), required=False) - def clean_escapechar(self): + def clean_escapechar(self) -> str | None: return self.cleaned_data["escapechar"] or None - def csv_fields(self): + def csv_fields(self) -> list[forms.Field]: return [ field for field in self @@ -87,9 +87,7 @@ class CSVOptions(CSVConfigForm): ) action = forms.CharField(label="", required=True, initial="", widget=forms.HiddenInput()) - datetime_format = forms.CharField( - label=_("Datetime format"), initial=formats.get_format("DATETIME_FORMAT") - ) + datetime_format = forms.CharField(label=_("Datetime format"), initial=formats.get_format("DATETIME_FORMAT")) date_format = forms.CharField(label=_("Date format"), initial=formats.get_format("DATE_FORMAT")) time_format = forms.CharField(label=_("Time format"), initial=formats.get_format("TIME_FORMAT")) columns = forms.MultipleChoiceField(label=_("Columns"), widget=SelectMultiple(attrs={"size": 20})) diff --git a/src/adminactions/graph.py b/src/adminactions/graph.py index 5eba4af0..e558b529 100644 --- a/src/adminactions/graph.py +++ b/src/adminactions/graph.py @@ -1,8 +1,10 @@ import json +from typing import TYPE_CHECKING from django.contrib import messages from django.contrib.admin import helpers from django.db.models.aggregates import Count +from django.db.models.base import Model from django.db.models.fields.related import ForeignKey from django.forms.fields import BooleanField, CharField, ChoiceField from django.forms.forms import DeclarativeFieldsMetaclass, Form @@ -16,8 +18,13 @@ from .signals import adminaction_end, adminaction_requested, adminaction_start from .utils import get_field_by_name +if TYPE_CHECKING: + from django.contrib.admin import ModelAdmin + from django.http.request import HttpRequest + from django.http.response import HttpResponse -def graph_form_factory(model): + +def graph_form_factory(model: Model) -> Form: app_name = model._meta.app_label model_name = model.__name__ @@ -38,7 +45,7 @@ def graph_form_factory(model): return DeclarativeFieldsMetaclass(str(class_name), (Form,), attrs) -def graph_queryset(modeladmin, request, queryset): # noqa +def graph_queryset(modeladmin: "ModelAdmin", request: "HttpRequest", queryset: "QuerySet") -> "HTTPResponse": # noqa opts = modeladmin.model._meta perm = "{0}.{1}".format( opts.app_label.lower(), diff --git a/src/adminactions/helpers.py b/src/adminactions/helpers.py index 08d0ca55..b7634899 100644 --- a/src/adminactions/helpers.py +++ b/src/adminactions/helpers.py @@ -1,3 +1,5 @@ +from typing import TYPE_CHECKING, Any + from django import forms from django.contrib import messages from django.core import serializers @@ -6,6 +8,11 @@ from .perms import get_permission_codename +if TYPE_CHECKING: + from django.contrib.admin.options import ModelAdmin + from django.http.request import HttpRequest + from django.http.response import HttpResponse + class ImportFixtureForm(forms.Form): fixture_file = forms.FileField(required=False) @@ -14,12 +21,12 @@ class ImportFixtureForm(forms.Form): use_natural_foreign_keys = forms.BooleanField(required=False) use_natural_primary_keys = forms.BooleanField(required=False) - def clean(self): + def clean(self) -> None: if not (self.cleaned_data["fixture_file"] or self.cleaned_data["fixture_content"]): raise ValidationError("You must provide file or content") -def import_fixture(modeladmin, request): +def import_fixture(modeladmin: "ModelAdmin", request: "HttpRequest") -> "HttpResponse": context = modeladmin.get_common_context(request) if request.method == "POST": form = ImportFixtureForm(data=request.POST) @@ -57,7 +64,9 @@ def import_fixture(modeladmin, request): class AdminActionPermMixin: - def _filter_actions_by_permissions(self, request, actions): + def _filter_actions_by_permissions( + self, request: "HttpRequest", actions: list[tuple[callable, Any]] + ) -> list[tuple[callable, Any]]: opts = self.model._meta filtered_actions = [] actions = super()._filter_actions_by_permissions(request, actions) diff --git a/src/adminactions/management/commands/create_extra_permissions.py b/src/adminactions/management/commands/create_extra_permissions.py index 775f8516..7ebfaff1 100644 --- a/src/adminactions/management/commands/create_extra_permissions.py +++ b/src/adminactions/management/commands/create_extra_permissions.py @@ -1,8 +1,10 @@ +from typing import Any + from django.core.management import BaseCommand class Command(BaseCommand): - def handle(self, *args, **options): + def handle(self, *args: Any, **options: Any) -> None: from adminactions.perms import create_extra_permissions create_extra_permissions() diff --git a/src/adminactions/mass_update.py b/src/adminactions/mass_update.py index 6f182198..d3ac78e5 100644 --- a/src/adminactions/mass_update.py +++ b/src/adminactions/mass_update.py @@ -1,7 +1,10 @@ +from __future__ import annotations + import logging import re from collections import OrderedDict as SortedDict from collections import defaultdict +from typing import TYPE_CHECKING, Any from django import forms from django.conf import settings @@ -34,6 +37,11 @@ from .signals import adminaction_end, adminaction_requested, adminaction_start from .utils import curry, get_field_by_name +if TYPE_CHECKING: + from django.db.models.query import QuerySet + from django.http.request import HttpRequest + + logger = logging.getLogger(__name__) DO_NOT_MASS_UPDATE = "do_NOT_mass_UPDATE" @@ -74,82 +82,80 @@ class OperationManager: ("set null", (lambda old_value: None, False, disable_if_not_nullable, "")), ] - def __init__(self, _dict): + def __init__(self, _dict: dict[type[df.Field], tuple[str, Any]]) -> None: self._dict = defaultdict(SortedDict) self.operations = dict() self.register_operations(df.Field, self.COMMON) for field_class, args in _dict.items(): self.register_operations(field_class, args) - def register_operations(self, field_class, operations): + def register_operations( + self, field_class: type[df.Field], operations: list[tuple[str, tuple[Any, bool, callable, str]]] + ) -> None: for label, operation in operations: self._dict[field_class][label] = operation if operation: self.operations[label] = operation[0] - def get_function(self, name): + def get_function(self, name: str) -> callable: return self.operations.get(name, None) - def get(self, field_class: type): + def get(self, field_class: type[df.Field]) -> dict[type[df.Field]]: data = SortedDict() # reversed to make the most specific overrule the more general ones for typ in reversed(field_class.__mro__): data |= self._dict.get(typ, ()) return data - def operation_enabled(self, field, operation): + def operation_enabled(self, field: df.Field, operation: tuple[Any, Any, Any]) -> bool: if operation: enabler = operation[2] return enabler is True or (callable(enabler) and enabler(field)) return False - def get_for_field(self, field): + def get_for_field(self, field: df.Field) -> dict[str, callable]: """returns valid functions for passed field :param field Field django Model Field :return list of (label, (__, param, enabler, help)) """ - return SortedDict( - [ - (label, operation) - for label, operation in self.get(field.__class__).items() - if self.operation_enabled(field, operation) - ] - ) + return SortedDict([ + (label, operation) + for label, operation in self.get(field.__class__).items() + if self.operation_enabled(field, operation) + ]) - def __getitem__(self, field_class): + def __getitem__(self, field_class: type[df.Field]) -> dict[type[df.Field]]: return self.get(field_class) -OPERATIONS = OperationManager( - { - df.CharField: [ - ("upper", (str.upper, False, True, _("convert to uppercase"))), - ("lower", (str.lower, False, True, _("convert to lowercase"))), - ( - "capitalize", - (str.capitalize, False, True, _("capitalize first character")), - ), - ("trim", (str.strip, False, True, _("leading and trailing whitespace"))), - ], - df.IntegerField: [ - ( - "add percent", - (add_percent, True, True, _("add percent to existing value")), - ), - ("sub percent", (sub_percent, True, True, "")), - ("sub", (sub_percent, True, True, "")), - ("add", (add, True, True, "")), - ], - df.BooleanField: [("toggle", (negate, False, True, ""))], - # df.NullBooleanField: [("toggle", (negate, False, True, ""))], - df.EmailField: [ - ("change domain", (change_domain, True, True, "")), - ("upper", (str.upper, False, True, _("convert to uppercase"))), - ("lower", (str.lower, False, True, _("convert to lowercase"))), - ], - df.URLField: [("change protocol", (change_protocol, True, True, ""))], - } -) +OPERATIONS = OperationManager({ + df.CharField: [ + ("upper", (str.upper, False, True, _("convert to uppercase"))), + ("lower", (str.lower, False, True, _("convert to lowercase"))), + ( + "capitalize", + (str.capitalize, False, True, _("capitalize first character")), + ), + ("trim", (str.strip, False, True, _("leading and trailing whitespace"))), + ], + df.IntegerField: [ + ( + "add percent", + (add_percent, True, True, _("add percent to existing value")), + ), + ("sub percent", (sub_percent, True, True, "")), + ("sub", (sub_percent, True, True, "")), + ("add", (add, True, True, "")), + ], + df.BooleanField: [("toggle", (negate, False, True, ""))], + # df.NullBooleanField: [("toggle", (negate, False, True, ""))], + df.EmailField: [ + ("change domain", (change_domain, True, True, "")), + ("upper", (str.upper, False, True, _("convert to uppercase"))), + ("lower", (str.lower, False, True, _("convert to lowercase"))), + ], + df.URLField: [("change protocol", (change_protocol, True, True, ""))], +}) class MassUpdateForm(GenericActionForm): @@ -167,7 +173,7 @@ class MassUpdateForm(GenericActionForm): ) sort_fields = True - def __init__(self, *args, **kwargs): + def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self._errors = None self.update_using_queryset_allowed = True @@ -177,7 +183,7 @@ def __init__(self, *args, **kwargs): if self.sort_fields: self.fields = {k: v for k, v in sorted(self.fields.items(), key=lambda item: item[1].label or "")} - def _get_validation_exclusions(self): + def _get_validation_exclusions(self) -> list[str]: exclude = list(super()._get_validation_exclusions()) for name, field in list(self.fields.items()): function = self.data.get("func_id_%s" % name, False) @@ -185,7 +191,7 @@ def _get_validation_exclusions(self): exclude.append(name) return exclude - def _post_clean(self): + def _post_clean(self) -> None: # must be overriden to bypass instance.clean() if self.cleaned_data.get("_clean", False): opts = self._meta @@ -200,7 +206,7 @@ def _post_clean(self): except ValidationError as e: self._update_errors(e.message_dict) - def full_clean(self): + def full_clean(self) -> None: super().full_clean() if not self.is_bound: # Stop further processing. return @@ -217,10 +223,10 @@ def full_clean(self): if isinstance(self.fields.get(field_name, ""), ModelMultipleChoiceField): self.add_error( field_name, - _("Unable no mass update ManyToManyField" " without 'validate'"), + _("Unable no mass update ManyToManyField without 'validate'"), ) - def _clean_fields(self): + def _clean_fields(self) -> None: self.update_using_queryset_allowed = True for name, field in list(self.fields.items()): raw_value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name)) @@ -257,17 +263,17 @@ def _clean_fields(self): if name in self.cleaned_data: del self.cleaned_data[name] - def clean__validate(self): + def clean__validate(self) -> bool: return bool(self.data.get("_validate", 0)) - def clean__async(self): + def clean__async(self) -> bool: return bool(self.data.get("_async", 0)) - def clean__clean(self): + def clean__clean(self) -> bool: return bool(self.data.get("_clean", 0)) @property - def media(self): + def media(self) -> forms.Media: extra = "" if settings.DEBUG else ".min" return super().media + forms.Media( js=( @@ -279,13 +285,20 @@ def media(self): }, ) - def fix_json(self): + def fix_json(self) -> None: for label, field in self.fields.items(): if isinstance(field, forms.JSONField): field.disabled = label not in self.data -def mass_update_execute(queryset, rules, validate, clean, user_pk, request=None): +def mass_update_execute( + queryset: "QuerySet", + rules: dict[str, tuple[callable, Any]], + validate: bool, + clean: bool, + user_pk: Any, + request: "HttpRequest" | None = None, +) -> tuple[int, list[str]]: errors = {} updated = 0 opts = queryset.model._meta @@ -347,14 +360,14 @@ def mass_update(modeladmin, request, queryset): # noqa mass update queryset """ - def not_required(field, **kwargs): + def not_required(field: df.Field, **kwargs: Any) -> forms.Field: """force all fields as not required""" kwargs["required"] = False kwargs["request"] = request return modeladmin.formfield_for_dbfield(field, **kwargs) - def _get_sample(): - grouped = defaultdict(lambda: []) + def _get_sample() -> dict[str, list[tuple[Any, str] | dict[str, Any]]]: + grouped = defaultdict(list) for f in mass_update_hints: if isinstance(f, ForeignKey): # Filter by queryset so we only get results without our diff --git a/src/adminactions/merge.py b/src/adminactions/merge.py index 92e81c6a..478d0902 100644 --- a/src/adminactions/merge.py +++ b/src/adminactions/merge.py @@ -1,20 +1,24 @@ from datetime import datetime +from typing import Any, Generator from django import forms from django.contrib import messages from django.contrib.admin import helpers from django.db import models +from django.db.models.base import Model from django.forms import HiddenInput, TextInput +from django.forms.fields import Field from django.forms.formsets import formset_factory from django.forms.models import model_to_dict, modelform_factory from django.http import HttpResponseRedirect +from django.http.request import HttpRequest from django.shortcuts import render from django.utils.encoding import smart_str from django.utils.safestring import mark_safe from django.utils.translation import gettext as _ from . import api -from . import compat as transaction +from .compat import nocommit from .forms import GenericActionForm from .perms import get_permission_codename from .signals import adminaction_end, adminaction_requested, adminaction_start @@ -39,29 +43,20 @@ class MergeFormBase(forms.Form): other_pk = forms.CharField(widget=HiddenInput) field_names = forms.CharField(required=False, widget=HiddenInput) - def action_fields(self): + def action_fields(self) -> Generator[HiddenInput, None, None]: for field_name in ["dependencies", "master_pk", "other_pk", "field_names"]: bf = self[field_name] yield HiddenInput().render(field_name, bf.value()) - def clean_dependencies(self): + def clean_dependencies(self) -> int: return int(self.cleaned_data["dependencies"]) - def clean_field_names(self): + def clean_field_names(self) -> Any: if self.cleaned_data["field_names"]: return self.cleaned_data["field_names"].split(",") else: return None - def full_clean(self): - super().full_clean() - - def clean(self): - return super().clean() - - def is_valid(self): - return super().is_valid() - class Media: js = [ "admin/js/vendor/jquery/jquery.js", @@ -75,8 +70,7 @@ class MergeForm(GenericActionForm, MergeFormBase): pass -# noinspection PyProtectedMember -def merge(modeladmin, request, queryset): # noqa +def merge(modeladmin: "ModelAdmin", request: "HttpRequest", queryset: "QuerySet"): # noqa """ Merge two model instances. Move all foreign keys. @@ -88,7 +82,7 @@ def merge(modeladmin, request, queryset): # noqa messages.error(request, _("Sorry you do not have rights to execute this action")) return - def raw_widget(field, **kwargs): + def raw_widget(field: models.Field, **kwargs: Any) -> Field: """force all fields as not required""" kwargs["widget"] = TextInput({"class": "raw-value"}) if isinstance(field, models.FileField): @@ -105,11 +99,11 @@ def raw_widget(field, **kwargs): ) OForm = modelform_factory(modeladmin.model, exclude=("pk",), formfield_callback=raw_widget) - def validate(v_request, v_master, v_other): + def validate(v_request: HttpRequest, v_master: Model, v_other: Model) -> None: """Validate the model is still valid after the merge""" v_merge_kwargs = {} - with transaction.nocommit(): + with nocommit(): merge_form_base = MergeFormBase(v_request.POST) if merge_form_base.is_valid(): @@ -141,9 +135,7 @@ def validate(v_request, v_master, v_other): "select_across": request.POST.get("select_across") == "1", "action": request.POST.get("action"), "fields": [ - f - for f in queryset.model._meta.fields - if not f.primary_key and f.editable and f.name not in ignored_fields + f for f in queryset.model._meta.fields if not f.primary_key and f.editable and f.name not in ignored_fields ], "app_label": queryset.model._meta.app_label, "result": "", @@ -236,21 +228,19 @@ def validate(v_request, v_master, v_other): adminForm = helpers.AdminForm(form, modeladmin.get_fieldsets(request), {}, [], model_admin=modeladmin) media = modeladmin.media + adminForm.media - ctx.update( - { - "adminform": adminForm, - "formset": formset, - "media": mark_safe(media), - "action_short_description": merge.short_description, - "title": "%s (%s)" - % ( - merge.short_description.capitalize(), - smart_str(modeladmin.opts.verbose_name_plural), - ), - "master": master, - "other": other, - } - ) + ctx.update({ + "adminform": adminForm, + "formset": formset, + "media": mark_safe(media), + "action_short_description": merge.short_description, + "title": "%s (%s)" + % ( + merge.short_description.capitalize(), + smart_str(modeladmin.opts.verbose_name_plural), + ), + "master": master, + "other": other, + }) ctx.update(modeladmin.admin_site.each_context(request)) return render(request, tpl, context=ctx) diff --git a/src/adminactions/models.py b/src/adminactions/models.py index 63e6a6da..2c94f2c1 100644 --- a/src/adminactions/models.py +++ b/src/adminactions/models.py @@ -1,9 +1,12 @@ +from typing import Any + +from django.db.models.base import Model from django.db.models.signals import post_migrate from . import config, consts, perms -def create_extra_permissions_handler(sender, **kwargs): +def create_extra_permissions_handler(sender: Model, **kwargs: Any) -> None: global TOTAL_MODELS, COUNTER if config.AA_PERMISSION_HANDLER == consts.AA_PERMISSION_CREATE_USE_SIGNAL: perms.create_extra_permissions() diff --git a/src/adminactions/perms.py b/src/adminactions/perms.py index 278c5eca..42394964 100644 --- a/src/adminactions/perms.py +++ b/src/adminactions/perms.py @@ -1,13 +1,21 @@ +from typing import TYPE_CHECKING + from django.apps import apps +from django.db.models.options import Options + +if TYPE_CHECKING: + from django.contrib.contenttypes.models import ContentType __all__ = ["create_extra_permissions", "get_permission_codename"] +from django.db.models.base import Model + -def get_permission_codename(action, opts): +def get_permission_codename(action: str, opts: Options) -> str: return "%s_%s" % (action, opts.object_name.lower()) -def get_contenttype_for_model(model): +def get_contenttype_for_model(model: Model) -> "ContentType": from django.contrib.contenttypes.models import ContentType model = model._meta.concrete_model @@ -19,7 +27,7 @@ def get_contenttype_for_model(model): return ct -def create_extra_permissions(): +def create_extra_permissions() -> None: from django.contrib.auth.models import Permission from django.contrib.contenttypes.models import ContentType diff --git a/src/adminactions/py.typed b/src/adminactions/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/src/adminactions/static/adminactions/css/adminactions.css b/src/adminactions/static/adminactions/css/adminactions.css index 05085076..163a9e25 100644 --- a/src/adminactions/static/adminactions/css/adminactions.css +++ b/src/adminactions/static/adminactions/css/adminactions.css @@ -1 +1,50 @@ -.mergetable{width:100%;border:1px solid #000}p.display{width:300px;overflow:hidden;white-space:nowrap}.mergetable tr.header th{font-weight:bold;text-align:center}.mergetable td{vertical-align:middle;border-right:1px solid #000}.mergetable .label{font-weight:bold}.mergetable .selected{background-color:#81b10c}.mergetable .changed{background-color:#f9adaf}.mergetable input.raw-value{border:0px transparent;background-color:transparent;display:none}div.duplicates{display:flex}div.duplicates table{width:100%}div.duplicates table tr th{white-space:nowrap}div.duplicates .left{flex-shrink:initial}div.duplicates .right{border:1px solid #c9c9c9;margin-left:40px;padding:5px;flex-grow:initial;width:100%}/*# sourceMappingURL=adminactions.css.map */ +.mergetable { + width: 100%; + border: 1px solid #000; +} +p.display { + width: 300px; + overflow: hidden; + white-space: nowrap; +} +.mergetable tr.header th { + font-weight: bold; + text-align: center; +} +.mergetable td { + vertical-align: middle; + border-right: 1px solid #000; +} +.mergetable .label { + font-weight: bold; +} +.mergetable .selected { + background-color: #81b10c; +} +.mergetable .changed { + background-color: #f9adaf; +} +.mergetable input.raw-value { + border: 0px transparent; + background-color: transparent; + display: none; +} +div.duplicates { + display: flex; +} +div.duplicates table { + width: 100%; +} +div.duplicates table tr th { + white-space: nowrap; +} +div.duplicates .left { + flex-shrink: initial; +} +div.duplicates .right { + border: 1px solid #c9c9c9; + margin-left: 40px; + padding: 5px; + flex-grow: initial; + width: 100%; +} /*# sourceMappingURL=adminactions.css.map */ diff --git a/src/adminactions/static/adminactions/css/adminactions.css.map b/src/adminactions/static/adminactions/css/adminactions.css.map index 1ecf7128..9ca85c6d 100644 --- a/src/adminactions/static/adminactions/css/adminactions.css.map +++ b/src/adminactions/static/adminactions/css/adminactions.css.map @@ -1 +1 @@ -{"version":3,"sourceRoot":"","sources":["adminactions.scss"],"names":[],"mappings":"AAAA,YACI,WACA,sBAEJ,UACI,YACA,gBACA,mBAIJ,yBACI,iBACA,kBAGJ,eAEI,sBACA,4BAaJ,mBAEI,iBAGJ,sBACI,yBAGJ,qBACI,yBAGJ,4BAEI,uBACA,6BACA,aAGJ,eAOI,aANA,qBACI,WACA,2BACI,mBAIR,qBACI,oBAEJ,sBACI,yBACA,iBACA,YACA,kBACA","file":"adminactions.css"} \ No newline at end of file +{"version":3,"sourceRoot":"","sources":["adminactions.scss"],"names":[],"mappings":"AAAA,YACI,WACA,sBAEJ,UACI,YACA,gBACA,mBAIJ,yBACI,iBACA,kBAGJ,eAEI,sBACA,4BAaJ,mBAEI,iBAGJ,sBACI,yBAGJ,qBACI,yBAGJ,4BAEI,uBACA,6BACA,aAGJ,eAOI,aANA,qBACI,WACA,2BACI,mBAIR,qBACI,oBAEJ,sBACI,yBACA,iBACA,YACA,kBACA","file":"adminactions.css"} diff --git a/src/adminactions/static/adminactions/css/adminactions.scss b/src/adminactions/static/adminactions/css/adminactions.scss index 1aa757cf..2defd8a4 100644 --- a/src/adminactions/static/adminactions/css/adminactions.scss +++ b/src/adminactions/static/adminactions/css/adminactions.scss @@ -21,10 +21,11 @@ p.display { } .mergetable .column { - /*width: 30%;*/ + /*width: 30%;*/ } -.mergetable .origin *, .mergetable .result * { +.mergetable .origin *, +.mergetable .result * { /*width: 30%;*/ /*word-wrap: break-word;*/ /*white-space:pre-line;*/ @@ -50,18 +51,18 @@ p.display { display: none; } -div.duplicates{ - table{ +div.duplicates { + table { width: 100%; tr th { white-space: nowrap; } } display: flex; - .left{ + .left { flex-shrink: initial; } - .right{ + .right { border: 1px solid #c9c9c9; margin-left: 40px; padding: 5px; diff --git a/src/adminactions/static/adminactions/css/bulkupdate.css b/src/adminactions/static/adminactions/css/bulkupdate.css index 1a40f7d8..354b1357 100644 --- a/src/adminactions/static/adminactions/css/bulkupdate.css +++ b/src/adminactions/static/adminactions/css/bulkupdate.css @@ -1 +1,29 @@ -table th.title{background-color:var(--header-bg)}table.bulk-update{border:1px solid #c9c9c9}table.bulk-update td{border-left:1px solid #c9c9c9}table.bulk-update select.func_select{min-width:100px}#col1{float:left;width:70%}#col1 table{width:90%}#col2{float:right;width:30%}#col2 table{width:90%}#col2 select{width:100%}/*# sourceMappingURL=bulkupdate.css.map */ +table th.title { + background-color: var(--header-bg); +} +table.bulk-update { + border: 1px solid #c9c9c9; +} +table.bulk-update td { + border-left: 1px solid #c9c9c9; +} +table.bulk-update select.func_select { + min-width: 100px; +} +#col1 { + float: left; + width: 70%; +} +#col1 table { + width: 90%; +} +#col2 { + float: right; + width: 30%; +} +#col2 table { + width: 90%; +} +#col2 select { + width: 100%; +} /*# sourceMappingURL=bulkupdate.css.map */ diff --git a/src/adminactions/static/adminactions/css/bulkupdate.css.map b/src/adminactions/static/adminactions/css/bulkupdate.css.map index 8469433a..108a6e20 100644 --- a/src/adminactions/static/adminactions/css/bulkupdate.css.map +++ b/src/adminactions/static/adminactions/css/bulkupdate.css.map @@ -1 +1 @@ -{"version":3,"sourceRoot":"","sources":["bulkupdate.scss"],"names":[],"mappings":"AACI,eACI,kCAGJ,kBACI,yBAEA,qBACI,8BAGJ,qCACI,gBASZ,MACI,WAEA,UAEA,YACI,UAIR,MACI,YACA,UAEA,YACI,UAIR,aACI","file":"bulkupdate.css"} \ No newline at end of file +{"version":3,"sourceRoot":"","sources":["bulkupdate.scss"],"names":[],"mappings":"AACI,eACI,kCAGJ,kBACI,yBAEA,qBACI,8BAGJ,qCACI,gBASZ,MACI,WAEA,UAEA,YACI,UAIR,MACI,YACA,UAEA,YACI,UAIR,aACI","file":"bulkupdate.css"} diff --git a/src/adminactions/static/adminactions/css/bulkupdate.scss b/src/adminactions/static/adminactions/css/bulkupdate.scss index 82e4dd4c..2b34af9b 100644 --- a/src/adminactions/static/adminactions/css/bulkupdate.scss +++ b/src/adminactions/static/adminactions/css/bulkupdate.scss @@ -14,10 +14,8 @@ table { min-width: 100px; } } - &.bulk-update-results { - - } - + &.bulk-update-results { + } } #col1 { diff --git a/src/adminactions/static/adminactions/css/massupdate.css b/src/adminactions/static/adminactions/css/massupdate.css index 13f726dc..0191bb49 100644 --- a/src/adminactions/static/adminactions/css/massupdate.css +++ b/src/adminactions/static/adminactions/css/massupdate.css @@ -1 +1,20 @@ -table.mass-update{border:1px solid #c9c9c9}table.mass-update td{border-left:1px solid #c9c9c9}table.mass-update select.func_select{min-width:100px}#col1{float:left;width:70%}#col2{float:right;width:30%}#col2 select{width:100%}/*# sourceMappingURL=massupdate.css.map */ +table.mass-update { + border: 1px solid #c9c9c9; +} +table.mass-update td { + border-left: 1px solid #c9c9c9; +} +table.mass-update select.func_select { + min-width: 100px; +} +#col1 { + float: left; + width: 70%; +} +#col2 { + float: right; + width: 30%; +} +#col2 select { + width: 100%; +} /*# sourceMappingURL=massupdate.css.map */ diff --git a/src/adminactions/static/adminactions/css/massupdate.css.map b/src/adminactions/static/adminactions/css/massupdate.css.map index 7456d113..6b628184 100644 --- a/src/adminactions/static/adminactions/css/massupdate.css.map +++ b/src/adminactions/static/adminactions/css/massupdate.css.map @@ -1 +1 @@ -{"version":3,"sourceRoot":"","sources":["massupdate.scss"],"names":[],"mappings":"AACA,kBACI,yBAEA,qBACI,8BAGJ,qCACI,gBAIR,MACI,WACA,UAGJ,MACI,YACA,UAGJ,aACI","file":"massupdate.css"} \ No newline at end of file +{"version":3,"sourceRoot":"","sources":["massupdate.scss"],"names":[],"mappings":"AACA,kBACI,yBAEA,qBACI,8BAGJ,qCACI,gBAIR,MACI,WACA,UAGJ,MACI,YACA,UAGJ,aACI","file":"massupdate.css"} diff --git a/src/adminactions/static/adminactions/css/massupdate.scss b/src/adminactions/static/adminactions/css/massupdate.scss index 7a0361d2..c6a6cb8d 100644 --- a/src/adminactions/static/adminactions/css/massupdate.scss +++ b/src/adminactions/static/adminactions/css/massupdate.scss @@ -1,4 +1,3 @@ - table.mass-update { border: 1px solid #c9c9c9; diff --git a/src/adminactions/static/adminactions/js/bulkupdate.js b/src/adminactions/static/adminactions/js/bulkupdate.js index b210eaab..4370e4e6 100644 --- a/src/adminactions/static/adminactions/js/bulkupdate.js +++ b/src/adminactions/static/adminactions/js/bulkupdate.js @@ -15,19 +15,18 @@ var data = localStorage.getItem(model); if (data) { $.each(formData, function (i, pair) { - $("input[name='" + pair.name + "']").val(pair.value); + $("input[name='" + pair.name + "']").val(pair.value); // $("td.col_field.field-" + pair.name + "-value input").val(pair.value); }); } $("#sel-cmd").val(""); } else if (this.value === "default") { - $('td.col_field').each(function () { - $(this).find('input').val($(this).data('col')) + $("td.col_field").each(function () { + $(this).find("input").val($(this).data("col")); }); $("#sel-cmd").val(""); - } - }) + }); // console.log(formData); }); diff --git a/src/adminactions/static/adminactions/js/jqplot/MIT-LICENSE.txt b/src/adminactions/static/adminactions/js/jqplot/MIT-LICENSE.txt index f8111b9c..5d43e39a 100644 --- a/src/adminactions/static/adminactions/js/jqplot/MIT-LICENSE.txt +++ b/src/adminactions/static/adminactions/js/jqplot/MIT-LICENSE.txt @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. \ No newline at end of file +THE SOFTWARE. diff --git a/src/adminactions/static/adminactions/js/jqplot/README.txt b/src/adminactions/static/adminactions/js/jqplot/README.txt index 8777a20c..359832a8 100644 --- a/src/adminactions/static/adminactions/js/jqplot/README.txt +++ b/src/adminactions/static/adminactions/js/jqplot/README.txt @@ -21,8 +21,8 @@ Bugs, issues, feature requests: @@ -36,23 +36,23 @@ For usage instructions, see in usage.txt. For available options, Building from source: If you've cloned the repository, you can build a distribution from source. -You need to have ant installed. You can simply -type "ant" from the jqplot directory to build the default "all" target. +You need to have ant installed. You can simply +type "ant" from the jqplot directory to build the default "all" target. There are 6 pertinent targets: clean, dist, min, docs, compress and all. Use: > ant -p -to get a description of the various build targets. +to get a description of the various build targets. Legal Notices: Copyright (c) 2009-2013 Chris Leonello -jqPlot is currently available for use in all personal or commercial projects -under both the MIT and GPL version 2.0 licenses. This means that you can -choose the license that best suits your project and use it accordingly. +jqPlot is currently available for use in all personal or commercial projects +under both the MIT and GPL version 2.0 licenses. This means that you can +choose the license that best suits your project and use it accordingly. -Although not required, the author would appreciate an email letting him -know of any substantial use of jqPlot. You can reach the author at: +Although not required, the author would appreciate an email letting him +know of any substantial use of jqPlot. You can reach the author at: chris at jqplot or see http://www.jqplot.com/info.php . If you are feeling kind and generous, consider supporting the project by @@ -64,7 +64,7 @@ Date instance methods: author Ken Snyder (ken d snyder at gmail dot com) date 2008-09-10 - version 2.0.2 (http://kendsnyder.com/sandbox/date/) + version 2.0.2 (http://kendsnyder.com/sandbox/date/) license Creative Commons Attribution License 3.0 (http://creativecommons.org/licenses/by/3.0/) JavaScript printf/sprintf functions. diff --git a/src/adminactions/static/adminactions/js/jqplot/jquery.jqplot.css b/src/adminactions/static/adminactions/js/jqplot/jquery.jqplot.css index f6768a6a..f2f35003 100644 --- a/src/adminactions/static/adminactions/js/jqplot/jquery.jqplot.css +++ b/src/adminactions/static/adminactions/js/jqplot/jquery.jqplot.css @@ -4,7 +4,7 @@ color: #666666; font-family: "Trebuchet MS", Arial, Helvetica, sans-serif; font-size: 1em; -/* height: 300px; + /* height: 300px; width: 400px;*/ } @@ -25,23 +25,42 @@ margin-right: 10px; } -.jqplot-y2axis, .jqplot-y3axis, .jqplot-y4axis, .jqplot-y5axis, .jqplot-y6axis, .jqplot-y7axis, .jqplot-y8axis, .jqplot-y9axis, .jqplot-yMidAxis { +.jqplot-y2axis, +.jqplot-y3axis, +.jqplot-y4axis, +.jqplot-y5axis, +.jqplot-y6axis, +.jqplot-y7axis, +.jqplot-y8axis, +.jqplot-y9axis, +.jqplot-yMidAxis { margin-left: 10px; margin-right: 10px; } /*rules applied to all axis tick divs*/ -.jqplot-axis-tick, .jqplot-xaxis-tick, .jqplot-yaxis-tick, .jqplot-x2axis-tick, .jqplot-y2axis-tick, .jqplot-y3axis-tick, .jqplot-y4axis-tick, .jqplot-y5axis-tick, .jqplot-y6axis-tick, .jqplot-y7axis-tick, .jqplot-y8axis-tick, .jqplot-y9axis-tick, .jqplot-yMidAxis-tick { +.jqplot-axis-tick, +.jqplot-xaxis-tick, +.jqplot-yaxis-tick, +.jqplot-x2axis-tick, +.jqplot-y2axis-tick, +.jqplot-y3axis-tick, +.jqplot-y4axis-tick, +.jqplot-y5axis-tick, +.jqplot-y6axis-tick, +.jqplot-y7axis-tick, +.jqplot-y8axis-tick, +.jqplot-y9axis-tick, +.jqplot-yMidAxis-tick { position: absolute; white-space: pre; } - .jqplot-xaxis-tick { top: 0px; /* initial position untill tick is drawn in proper place */ left: 15px; -/* padding-top: 10px;*/ + /* padding-top: 10px;*/ vertical-align: top; } @@ -49,7 +68,7 @@ bottom: 0px; /* initial position untill tick is drawn in proper place */ left: 15px; -/* padding-bottom: 10px;*/ + /* padding-bottom: 10px;*/ vertical-align: bottom; } @@ -57,25 +76,32 @@ right: 0px; /* initial position untill tick is drawn in proper place */ top: 15px; -/* padding-right: 10px;*/ + /* padding-right: 10px;*/ text-align: right; } .jqplot-yaxis-tick.jqplot-breakTick { right: -20px; margin-right: 0px; - padding:1px 5px 1px 5px; + padding: 1px 5px 1px 5px; /*background-color: white;*/ z-index: 2; font-size: 1.5em; } -.jqplot-y2axis-tick, .jqplot-y3axis-tick, .jqplot-y4axis-tick, .jqplot-y5axis-tick, .jqplot-y6axis-tick, .jqplot-y7axis-tick, .jqplot-y8axis-tick, .jqplot-y9axis-tick { +.jqplot-y2axis-tick, +.jqplot-y3axis-tick, +.jqplot-y4axis-tick, +.jqplot-y5axis-tick, +.jqplot-y6axis-tick, +.jqplot-y7axis-tick, +.jqplot-y8axis-tick, +.jqplot-y9axis-tick { left: 0px; /* initial position untill tick is drawn in proper place */ top: 15px; -/* padding-left: 10px;*/ -/* padding-right: 15px;*/ + /* padding-left: 10px;*/ + /* padding-right: 15px;*/ text-align: left; } @@ -98,7 +124,7 @@ .jqplot-yaxis-label { margin-right: 10px; -/* text-align: center;*/ + /* text-align: center;*/ font-size: 11pt; position: absolute; } @@ -108,8 +134,15 @@ position: absolute; } -.jqplot-y2axis-label, .jqplot-y3axis-label, .jqplot-y4axis-label, .jqplot-y5axis-label, .jqplot-y6axis-label, .jqplot-y7axis-label, .jqplot-y8axis-label, .jqplot-y9axis-label { -/* text-align: center;*/ +.jqplot-y2axis-label, +.jqplot-y3axis-label, +.jqplot-y4axis-label, +.jqplot-y5axis-label, +.jqplot-y6axis-label, +.jqplot-y7axis-label, +.jqplot-y8axis-label, +.jqplot-y9axis-label { + /* text-align: center;*/ font-size: 11pt; margin-left: 10px; position: absolute; @@ -132,15 +165,16 @@ table.jqplot-table-legend { margin-right: 12px; } -table.jqplot-table-legend, table.jqplot-cursor-legend { - background-color: rgba(255,255,255,0.6); +table.jqplot-table-legend, +table.jqplot-cursor-legend { + background-color: rgba(255, 255, 255, 0.6); border: 1px solid #cccccc; position: absolute; font-size: 0.75em; } td.jqplot-table-legend { - vertical-align:middle; + vertical-align: middle; } /* @@ -159,7 +193,8 @@ tr.jqplot-table-legend:first td.jqplot-table-legend-swatch { } */ -td.jqplot-seriesToggle:hover, td.jqplot-seriesToggle:active { +td.jqplot-seriesToggle:hover, +td.jqplot-seriesToggle:active { cursor: pointer; } @@ -169,12 +204,12 @@ td.jqplot-seriesToggle:hover, td.jqplot-seriesToggle:active { div.jqplot-table-legend-swatch-outline { border: 1px solid #cccccc; - padding:1px; + padding: 1px; } div.jqplot-table-legend-swatch { - width:0px; - height:0px; + width: 0px; + height: 0px; border-top-width: 5px; border-bottom-width: 5px; border-left-width: 6px; @@ -197,20 +232,20 @@ table.jqplot-cursor-tooltip { font-size: 0.75em; } - .jqplot-cursor-tooltip { border: 1px solid #cccccc; font-size: 0.75em; white-space: nowrap; - background: rgba(208,208,208,0.5); + background: rgba(208, 208, 208, 0.5); padding: 1px; } -.jqplot-highlighter-tooltip, .jqplot-canvasOverlay-tooltip { +.jqplot-highlighter-tooltip, +.jqplot-canvasOverlay-tooltip { border: 1px solid #cccccc; font-size: 0.75em; white-space: nowrap; - background: rgba(208,208,208,0.5); + background: rgba(208, 208, 208, 0.5); padding: 1px; } @@ -218,7 +253,7 @@ table.jqplot-cursor-tooltip { font-size: 0.75em; z-index: 2; } - + td.jqplot-cursor-legend-swatch { vertical-align: middle; text-align: center; @@ -230,12 +265,12 @@ div.jqplot-cursor-legend-swatch { } .jqplot-error { -/* Styles added to the plot target container when there is an error go here.*/ + /* Styles added to the plot target container when there is an error go here.*/ text-align: center; } .jqplot-error-message { -/* Styling of the custom error message div goes here.*/ + /* Styling of the custom error message div goes here.*/ position: relative; top: 46%; display: inline-block; @@ -243,7 +278,7 @@ div.jqplot-cursor-legend-swatch { div.jqplot-bubble-label { font-size: 0.8em; -/* background: rgba(90%, 90%, 90%, 0.15);*/ + /* background: rgba(90%, 90%, 90%, 0.15);*/ padding-left: 2px; padding-right: 2px; color: rgb(20%, 20%, 20%); diff --git a/src/adminactions/static/adminactions/js/jqplot/jquery.jqplot.min.css b/src/adminactions/static/adminactions/js/jqplot/jquery.jqplot.min.css index 0f84835b..d80dd94b 100644 --- a/src/adminactions/static/adminactions/js/jqplot/jquery.jqplot.min.css +++ b/src/adminactions/static/adminactions/js/jqplot/jquery.jqplot.min.css @@ -1 +1,220 @@ -.jqplot-target{position:relative;color:#666;font-family:"Trebuchet MS",Arial,Helvetica,sans-serif;font-size:1em}.jqplot-axis{font-size:.75em}.jqplot-xaxis{margin-top:10px}.jqplot-x2axis{margin-bottom:10px}.jqplot-yaxis{margin-right:10px}.jqplot-y2axis,.jqplot-y3axis,.jqplot-y4axis,.jqplot-y5axis,.jqplot-y6axis,.jqplot-y7axis,.jqplot-y8axis,.jqplot-y9axis,.jqplot-yMidAxis{margin-left:10px;margin-right:10px}.jqplot-axis-tick,.jqplot-xaxis-tick,.jqplot-yaxis-tick,.jqplot-x2axis-tick,.jqplot-y2axis-tick,.jqplot-y3axis-tick,.jqplot-y4axis-tick,.jqplot-y5axis-tick,.jqplot-y6axis-tick,.jqplot-y7axis-tick,.jqplot-y8axis-tick,.jqplot-y9axis-tick,.jqplot-yMidAxis-tick{position:absolute;white-space:pre}.jqplot-xaxis-tick{top:0;left:15px;vertical-align:top}.jqplot-x2axis-tick{bottom:0;left:15px;vertical-align:bottom}.jqplot-yaxis-tick{right:0;top:15px;text-align:right}.jqplot-yaxis-tick.jqplot-breakTick{right:-20px;margin-right:0;padding:1px 5px 1px 5px;z-index:2;font-size:1.5em}.jqplot-y2axis-tick,.jqplot-y3axis-tick,.jqplot-y4axis-tick,.jqplot-y5axis-tick,.jqplot-y6axis-tick,.jqplot-y7axis-tick,.jqplot-y8axis-tick,.jqplot-y9axis-tick{left:0;top:15px;text-align:left}.jqplot-yMidAxis-tick{text-align:center;white-space:nowrap}.jqplot-xaxis-label{margin-top:10px;font-size:11pt;position:absolute}.jqplot-x2axis-label{margin-bottom:10px;font-size:11pt;position:absolute}.jqplot-yaxis-label{margin-right:10px;font-size:11pt;position:absolute}.jqplot-yMidAxis-label{font-size:11pt;position:absolute}.jqplot-y2axis-label,.jqplot-y3axis-label,.jqplot-y4axis-label,.jqplot-y5axis-label,.jqplot-y6axis-label,.jqplot-y7axis-label,.jqplot-y8axis-label,.jqplot-y9axis-label{font-size:11pt;margin-left:10px;position:absolute}.jqplot-meterGauge-tick{font-size:.75em;color:#999}.jqplot-meterGauge-label{font-size:1em;color:#999}table.jqplot-table-legend{margin-top:12px;margin-bottom:12px;margin-left:12px;margin-right:12px}table.jqplot-table-legend,table.jqplot-cursor-legend{background-color:rgba(255,255,255,0.6);border:1px solid #ccc;position:absolute;font-size:.75em}td.jqplot-table-legend{vertical-align:middle}td.jqplot-seriesToggle:hover,td.jqplot-seriesToggle:active{cursor:pointer}.jqplot-table-legend .jqplot-series-hidden{text-decoration:line-through}div.jqplot-table-legend-swatch-outline{border:1px solid #ccc;padding:1px}div.jqplot-table-legend-swatch{width:0;height:0;border-top-width:5px;border-bottom-width:5px;border-left-width:6px;border-right-width:6px;border-top-style:solid;border-bottom-style:solid;border-left-style:solid;border-right-style:solid}.jqplot-title{top:0;left:0;padding-bottom:.5em;font-size:1.2em}table.jqplot-cursor-tooltip{border:1px solid #ccc;font-size:.75em}.jqplot-cursor-tooltip{border:1px solid #ccc;font-size:.75em;white-space:nowrap;background:rgba(208,208,208,0.5);padding:1px}.jqplot-highlighter-tooltip,.jqplot-canvasOverlay-tooltip{border:1px solid #ccc;font-size:.75em;white-space:nowrap;background:rgba(208,208,208,0.5);padding:1px}.jqplot-point-label{font-size:.75em;z-index:2}td.jqplot-cursor-legend-swatch{vertical-align:middle;text-align:center}div.jqplot-cursor-legend-swatch{width:1.2em;height:.7em}.jqplot-error{text-align:center}.jqplot-error-message{position:relative;top:46%;display:inline-block}div.jqplot-bubble-label{font-size:.8em;padding-left:2px;padding-right:2px;color:rgb(20%,20%,20%)}div.jqplot-bubble-label.jqplot-bubble-label-highlight{background:rgba(90%,90%,90%,0.7)}div.jqplot-noData-container{text-align:center;background-color:rgba(96%,96%,96%,0.3)} \ No newline at end of file +.jqplot-target { + position: relative; + color: #666; + font-family: "Trebuchet MS", Arial, Helvetica, sans-serif; + font-size: 1em; +} +.jqplot-axis { + font-size: 0.75em; +} +.jqplot-xaxis { + margin-top: 10px; +} +.jqplot-x2axis { + margin-bottom: 10px; +} +.jqplot-yaxis { + margin-right: 10px; +} +.jqplot-y2axis, +.jqplot-y3axis, +.jqplot-y4axis, +.jqplot-y5axis, +.jqplot-y6axis, +.jqplot-y7axis, +.jqplot-y8axis, +.jqplot-y9axis, +.jqplot-yMidAxis { + margin-left: 10px; + margin-right: 10px; +} +.jqplot-axis-tick, +.jqplot-xaxis-tick, +.jqplot-yaxis-tick, +.jqplot-x2axis-tick, +.jqplot-y2axis-tick, +.jqplot-y3axis-tick, +.jqplot-y4axis-tick, +.jqplot-y5axis-tick, +.jqplot-y6axis-tick, +.jqplot-y7axis-tick, +.jqplot-y8axis-tick, +.jqplot-y9axis-tick, +.jqplot-yMidAxis-tick { + position: absolute; + white-space: pre; +} +.jqplot-xaxis-tick { + top: 0; + left: 15px; + vertical-align: top; +} +.jqplot-x2axis-tick { + bottom: 0; + left: 15px; + vertical-align: bottom; +} +.jqplot-yaxis-tick { + right: 0; + top: 15px; + text-align: right; +} +.jqplot-yaxis-tick.jqplot-breakTick { + right: -20px; + margin-right: 0; + padding: 1px 5px 1px 5px; + z-index: 2; + font-size: 1.5em; +} +.jqplot-y2axis-tick, +.jqplot-y3axis-tick, +.jqplot-y4axis-tick, +.jqplot-y5axis-tick, +.jqplot-y6axis-tick, +.jqplot-y7axis-tick, +.jqplot-y8axis-tick, +.jqplot-y9axis-tick { + left: 0; + top: 15px; + text-align: left; +} +.jqplot-yMidAxis-tick { + text-align: center; + white-space: nowrap; +} +.jqplot-xaxis-label { + margin-top: 10px; + font-size: 11pt; + position: absolute; +} +.jqplot-x2axis-label { + margin-bottom: 10px; + font-size: 11pt; + position: absolute; +} +.jqplot-yaxis-label { + margin-right: 10px; + font-size: 11pt; + position: absolute; +} +.jqplot-yMidAxis-label { + font-size: 11pt; + position: absolute; +} +.jqplot-y2axis-label, +.jqplot-y3axis-label, +.jqplot-y4axis-label, +.jqplot-y5axis-label, +.jqplot-y6axis-label, +.jqplot-y7axis-label, +.jqplot-y8axis-label, +.jqplot-y9axis-label { + font-size: 11pt; + margin-left: 10px; + position: absolute; +} +.jqplot-meterGauge-tick { + font-size: 0.75em; + color: #999; +} +.jqplot-meterGauge-label { + font-size: 1em; + color: #999; +} +table.jqplot-table-legend { + margin-top: 12px; + margin-bottom: 12px; + margin-left: 12px; + margin-right: 12px; +} +table.jqplot-table-legend, +table.jqplot-cursor-legend { + background-color: rgba(255, 255, 255, 0.6); + border: 1px solid #ccc; + position: absolute; + font-size: 0.75em; +} +td.jqplot-table-legend { + vertical-align: middle; +} +td.jqplot-seriesToggle:hover, +td.jqplot-seriesToggle:active { + cursor: pointer; +} +.jqplot-table-legend .jqplot-series-hidden { + text-decoration: line-through; +} +div.jqplot-table-legend-swatch-outline { + border: 1px solid #ccc; + padding: 1px; +} +div.jqplot-table-legend-swatch { + width: 0; + height: 0; + border-top-width: 5px; + border-bottom-width: 5px; + border-left-width: 6px; + border-right-width: 6px; + border-top-style: solid; + border-bottom-style: solid; + border-left-style: solid; + border-right-style: solid; +} +.jqplot-title { + top: 0; + left: 0; + padding-bottom: 0.5em; + font-size: 1.2em; +} +table.jqplot-cursor-tooltip { + border: 1px solid #ccc; + font-size: 0.75em; +} +.jqplot-cursor-tooltip { + border: 1px solid #ccc; + font-size: 0.75em; + white-space: nowrap; + background: rgba(208, 208, 208, 0.5); + padding: 1px; +} +.jqplot-highlighter-tooltip, +.jqplot-canvasOverlay-tooltip { + border: 1px solid #ccc; + font-size: 0.75em; + white-space: nowrap; + background: rgba(208, 208, 208, 0.5); + padding: 1px; +} +.jqplot-point-label { + font-size: 0.75em; + z-index: 2; +} +td.jqplot-cursor-legend-swatch { + vertical-align: middle; + text-align: center; +} +div.jqplot-cursor-legend-swatch { + width: 1.2em; + height: 0.7em; +} +.jqplot-error { + text-align: center; +} +.jqplot-error-message { + position: relative; + top: 46%; + display: inline-block; +} +div.jqplot-bubble-label { + font-size: 0.8em; + padding-left: 2px; + padding-right: 2px; + color: rgb(20%, 20%, 20%); +} +div.jqplot-bubble-label.jqplot-bubble-label-highlight { + background: rgba(90%, 90%, 90%, 0.7); +} +div.jqplot-noData-container { + text-align: center; + background-color: rgba(96%, 96%, 96%, 0.3); +} diff --git a/src/adminactions/static/adminactions/js/jqplot/jquery.jqplot.min.js b/src/adminactions/static/adminactions/js/jqplot/jquery.jqplot.min.js index d015388d..b72a38ca 100644 --- a/src/adminactions/static/adminactions/js/jqplot/jquery.jqplot.min.js +++ b/src/adminactions/static/adminactions/js/jqplot/jquery.jqplot.min.js @@ -1 +1,9968 @@ -(function(L){var u;L.fn.emptyForce=function(){for(var ah=0,ai;(ai=L(this)[ah])!=null;ah++){if(ai.nodeType===1){L.cleanData(ai.getElementsByTagName("*"))}if(L.jqplot.use_excanvas){ai.outerHTML=""}else{while(ai.firstChild){ai.removeChild(ai.firstChild)}}ai=null}return L(this)};L.fn.removeChildForce=function(ah){while(ah.firstChild){this.removeChildForce(ah.firstChild);ah.removeChild(ah.firstChild)}};L.fn.jqplot=function(){var ah=[];var aj=[];for(var ak=0,ai=arguments.length;ak'+ao+"");L("#"+an).addClass("jqplot-error");document.getElementById(an).style.background=L.jqplot.config.errorBackground;document.getElementById(an).style.border=L.jqplot.config.errorBorder;document.getElementById(an).style.fontFamily=L.jqplot.config.errorFontFamily;document.getElementById(an).style.fontSize=L.jqplot.config.errorFontSize;document.getElementById(an).style.fontStyle=L.jqplot.config.errorFontStyle;document.getElementById(an).style.fontWeight=L.jqplot.config.errorFontWeight}}else{am.init(an,aj,ah);am.draw();am.themeEngine.init.call(am);return am}};L.jqplot.version="1.0.8";L.jqplot.revision="1250";L.jqplot.targetCounter=1;L.jqplot.CanvasManager=function(){if(typeof L.jqplot.CanvasManager.canvases=="undefined"){L.jqplot.CanvasManager.canvases=[];L.jqplot.CanvasManager.free=[]}var ah=[];this.getCanvas=function(){var ak;var aj=true;if(!L.jqplot.use_excanvas){for(var al=0,ai=L.jqplot.CanvasManager.canvases.length;al887){L.jqplot.support_canvas_text.result=true}else{L.jqplot.support_canvas_text.result=!!(document.createElement("canvas").getContext&&typeof document.createElement("canvas").getContext("2d").fillText=="function")}}return L.jqplot.support_canvas_text.result};L.jqplot.use_excanvas=((!L.support.boxModel||!L.support.objectAll||!$support.leadingWhitespace)&&!L.jqplot.support_canvas())?true:false;L.jqplot.preInitHooks=[];L.jqplot.postInitHooks=[];L.jqplot.preParseOptionsHooks=[];L.jqplot.postParseOptionsHooks=[];L.jqplot.preDrawHooks=[];L.jqplot.postDrawHooks=[];L.jqplot.preDrawSeriesHooks=[];L.jqplot.postDrawSeriesHooks=[];L.jqplot.preDrawLegendHooks=[];L.jqplot.addLegendRowHooks=[];L.jqplot.preSeriesInitHooks=[];L.jqplot.postSeriesInitHooks=[];L.jqplot.preParseSeriesOptionsHooks=[];L.jqplot.postParseSeriesOptionsHooks=[];L.jqplot.eventListenerHooks=[];L.jqplot.preDrawSeriesShadowHooks=[];L.jqplot.postDrawSeriesShadowHooks=[];L.jqplot.ElemContainer=function(){this._elem;this._plotWidth;this._plotHeight;this._plotDimensions={height:null,width:null}};L.jqplot.ElemContainer.prototype.createElement=function(ak,am,ai,aj,an){this._offsets=am;var ah=ai||"jqplot";var al=document.createElement(ak);this._elem=L(al);this._elem.addClass(ah);this._elem.css(aj);this._elem.attr(an);al=null;return this._elem};L.jqplot.ElemContainer.prototype.getWidth=function(){if(this._elem){return this._elem.outerWidth(true)}else{return null}};L.jqplot.ElemContainer.prototype.getHeight=function(){if(this._elem){return this._elem.outerHeight(true)}else{return null}};L.jqplot.ElemContainer.prototype.getPosition=function(){if(this._elem){return this._elem.position()}else{return{top:null,left:null,bottom:null,right:null}}};L.jqplot.ElemContainer.prototype.getTop=function(){return this.getPosition().top};L.jqplot.ElemContainer.prototype.getLeft=function(){return this.getPosition().left};L.jqplot.ElemContainer.prototype.getBottom=function(){return this._elem.css("bottom")};L.jqplot.ElemContainer.prototype.getRight=function(){return this._elem.css("right")};function w(ah){L.jqplot.ElemContainer.call(this);this.name=ah;this._series=[];this.show=false;this.tickRenderer=L.jqplot.AxisTickRenderer;this.tickOptions={};this.labelRenderer=L.jqplot.AxisLabelRenderer;this.labelOptions={};this.label=null;this.showLabel=true;this.min=null;this.max=null;this.autoscale=false;this.pad=1.2;this.padMax=null;this.padMin=null;this.ticks=[];this.numberTicks;this.tickInterval;this.renderer=L.jqplot.LinearAxisRenderer;this.rendererOptions={};this.showTicks=true;this.showTickMarks=true;this.showMinorTicks=true;this.drawMajorGridlines=true;this.drawMinorGridlines=false;this.drawMajorTickMarks=true;this.drawMinorTickMarks=true;this.useSeriesColor=false;this.borderWidth=null;this.borderColor=null;this.scaleToHiddenSeries=false;this._dataBounds={min:null,max:null};this._intervalStats=[];this._offsets={min:null,max:null};this._ticks=[];this._label=null;this.syncTicks=null;this.tickSpacing=75;this._min=null;this._max=null;this._tickInterval=null;this._numberTicks=null;this.__ticks=null;this._options={}}w.prototype=new L.jqplot.ElemContainer();w.prototype.constructor=w;w.prototype.init=function(){if(L.isFunction(this.renderer)){this.renderer=new this.renderer()}this.tickOptions.axis=this.name;if(this.tickOptions.showMark==null){this.tickOptions.showMark=this.showTicks}if(this.tickOptions.showMark==null){this.tickOptions.showMark=this.showTickMarks}if(this.tickOptions.showLabel==null){this.tickOptions.showLabel=this.showTicks}if(this.label==null||this.label==""){this.showLabel=false}else{this.labelOptions.label=this.label}if(this.showLabel==false){this.labelOptions.show=false}if(this.pad==0){this.pad=1}if(this.padMax==0){this.padMax=1}if(this.padMin==0){this.padMin=1}if(this.padMax==null){this.padMax=(this.pad-1)/2+1}if(this.padMin==null){this.padMin=(this.pad-1)/2+1}this.pad=this.padMax+this.padMin-1;if(this.min!=null||this.max!=null){this.autoscale=false}if(this.syncTicks==null&&this.name.indexOf("y")>-1){this.syncTicks=true}else{if(this.syncTicks==null){this.syncTicks=false}}this.renderer.init.call(this,this.rendererOptions)};w.prototype.draw=function(ah,ai){if(this.__ticks){this.__ticks=null}return this.renderer.draw.call(this,ah,ai)};w.prototype.set=function(){this.renderer.set.call(this)};w.prototype.pack=function(ai,ah){if(this.show){this.renderer.pack.call(this,ai,ah)}if(this._min==null){this._min=this.min;this._max=this.max;this._tickInterval=this.tickInterval;this._numberTicks=this.numberTicks;this.__ticks=this._ticks}};w.prototype.reset=function(){this.renderer.reset.call(this)};w.prototype.resetScale=function(ah){L.extend(true,this,{min:null,max:null,numberTicks:null,tickInterval:null,_ticks:[],ticks:[]},ah);this.resetDataBounds()};w.prototype.resetDataBounds=function(){var ao=this._dataBounds;ao.min=null;ao.max=null;var ai,ap,am;var aj=(this.show)?true:false;for(var al=0;alao.max)||ao.max==null){ao.max=am[ak][0]}}else{if((am[ak][ah]!=null&&am[ak][ah]ao.max)||ao.max==null){ao.max=am[ak][an]}}}if(aj&&ap.renderer.constructor!==L.jqplot.BarRenderer){aj=false}else{if(aj&&this._options.hasOwnProperty("forceTickAt0")&&this._options.forceTickAt0==false){aj=false}else{if(aj&&ap.renderer.constructor===L.jqplot.BarRenderer){if(ap.barDirection=="vertical"&&this.name!="xaxis"&&this.name!="x2axis"){if(this._options.pad!=null||this._options.padMin!=null){aj=false}}else{if(ap.barDirection=="horizontal"&&(this.name=="xaxis"||this.name=="x2axis")){if(this._options.pad!=null||this._options.padMin!=null){aj=false}}}}}}}}if(aj&&this.renderer.constructor===L.jqplot.LinearAxisRenderer&&ao.min>=0){this.padMin=1;this.forceTickAt0=true}};function q(ah){L.jqplot.ElemContainer.call(this);this.show=false;this.location="ne";this.labels=[];this.showLabels=true;this.showSwatches=true;this.placement="insideGrid";this.xoffset=0;this.yoffset=0;this.border;this.background;this.textColor;this.fontFamily;this.fontSize;this.rowSpacing="0.5em";this.renderer=L.jqplot.TableLegendRenderer;this.rendererOptions={};this.preDraw=false;this.marginTop=null;this.marginRight=null;this.marginBottom=null;this.marginLeft=null;this.escapeHtml=false;this._series=[];L.extend(true,this,ah)}q.prototype=new L.jqplot.ElemContainer();q.prototype.constructor=q;q.prototype.setOptions=function(ah){L.extend(true,this,ah);if(this.placement=="inside"){this.placement="insideGrid"}if(this.xoffset>0){if(this.placement=="insideGrid"){switch(this.location){case"nw":case"w":case"sw":if(this.marginLeft==null){this.marginLeft=this.xoffset+"px"}this.marginRight="0px";break;case"ne":case"e":case"se":default:if(this.marginRight==null){this.marginRight=this.xoffset+"px"}this.marginLeft="0px";break}}else{if(this.placement=="outside"){switch(this.location){case"nw":case"w":case"sw":if(this.marginRight==null){this.marginRight=this.xoffset+"px"}this.marginLeft="0px";break;case"ne":case"e":case"se":default:if(this.marginLeft==null){this.marginLeft=this.xoffset+"px"}this.marginRight="0px";break}}}this.xoffset=0}if(this.yoffset>0){if(this.placement=="outside"){switch(this.location){case"sw":case"s":case"se":if(this.marginTop==null){this.marginTop=this.yoffset+"px"}this.marginBottom="0px";break;case"ne":case"n":case"nw":default:if(this.marginBottom==null){this.marginBottom=this.yoffset+"px"}this.marginTop="0px";break}}else{if(this.placement=="insideGrid"){switch(this.location){case"sw":case"s":case"se":if(this.marginBottom==null){this.marginBottom=this.yoffset+"px"}this.marginTop="0px";break;case"ne":case"n":case"nw":default:if(this.marginTop==null){this.marginTop=this.yoffset+"px"}this.marginBottom="0px";break}}}this.yoffset=0}};q.prototype.init=function(){if(L.isFunction(this.renderer)){this.renderer=new this.renderer()}this.renderer.init.call(this,this.rendererOptions)};q.prototype.draw=function(ai,aj){for(var ah=0;ah');this.target.append(az);az.height(aD);az.width(aA);az.css("top",this.eventCanvas._offsets.top);az.css("left",this.eventCanvas._offsets.left);var aC=L('
');az.append(aC);aC.html(this.noDataIndicator.indicator);var aB=aC.height();var ax=aC.width();aC.height(aB);aC.width(ax);aC.css("top",(aD-aB)/2+"px")})}}this.data=L.extend(true,[],ar);this.parseOptions(ay);if(this.textColor){this.target.css("color",this.textColor)}if(this.fontFamily){this.target.css("font-family",this.fontFamily)}if(this.fontSize){this.target.css("font-size",this.fontSize)}this.title.init();this.legend.init();this._sumy=0;this._sumx=0;this.computePlotData();for(var at=0;at0){for(var aq=au;aq--;){var an=this._plotData[aq][ap][av];if(aw*an>=0){this._plotData[au][ap][av]+=an;this._stackData[au][ap][av]+=an;break}}}}}else{for(var ar=0;ar0){at._prevPlotData=this.series[au-1]._plotData}at._sumy=0;at._sumx=0;for(ar=at.data.length-1;ar>-1;ar--){at._sumy+=at.data[ar][1];at._sumx+=at.data[ar][0]}}};this.populatePlotData=function(au,av){this._plotData=[];this._stackData=[];au._stackData=[];au._plotData=[];var ay={x:[],y:[]};if(this.stackSeries&&!au.disableStack){au._stack=true;var ax=(au._stackAxis==="x")?0:1;var az=L.extend(true,[],au.data);var aA=L.extend(true,[],au.data);var an,am,ao,aw,al;for(var ar=0;ar=0){aA[aq][ax]+=aw}}}for(var at=0;at0){au._prevPlotData=this.series[av-1]._plotData}au._sumy=0;au._sumx=0;for(at=au.data.length-1;at>-1;at--){au._sumy+=au.data[at][1];au._sumx+=au.data[at][0]}};this.getNextSeriesColor=(function(am){var al=0;var an=am.seriesColors;return function(){if(al=0&&an>=0){al.top+=aK;al.bottom+=aK;al.left+=an;al.right+=an}}var am=["top","bottom","left","right"];for(var aB in am){if(this._gridPadding[am[aB]]==null&&al[am[aB]]>0){this._gridPadding[am[aB]]=al[am[aB]]}else{if(this._gridPadding[am[aB]]==null){this._gridPadding[am[aB]]=this._defaultGridPadding[am[aB]]}}}var aA=this._gridPadding;if(this.legend.placement==="outsideGrid"){aA={top:this.title.getHeight(),left:0,right:0,bottom:0};if(this.legend.location==="s"){aA.left=this._gridPadding.left;aA.right=this._gridPadding.right}}ar.xaxis.pack({position:"absolute",bottom:this._gridPadding.bottom-ar.xaxis.getHeight(),left:0,width:this._width},{min:this._gridPadding.left,max:this._width-this._gridPadding.right});ar.yaxis.pack({position:"absolute",top:0,left:this._gridPadding.left-ar.yaxis.getWidth(),height:this._height},{min:this._height-this._gridPadding.bottom,max:this._gridPadding.top});ar.x2axis.pack({position:"absolute",top:this._gridPadding.top-ar.x2axis.getHeight(),left:0,width:this._width},{min:this._gridPadding.left,max:this._width-this._gridPadding.right});for(aH=8;aH>0;aH--){ar[aG[aH-1]].pack({position:"absolute",top:0,right:this._gridPadding.right-az[aH-1]},{min:this._height-this._gridPadding.bottom,max:this._gridPadding.top})}var au=(this._width-this._gridPadding.left-this._gridPadding.right)/2+this._gridPadding.left-ar.yMidAxis.getWidth()/2;ar.yMidAxis.pack({position:"absolute",top:0,left:au,zIndex:9,textAlign:"center"},{min:this._height-this._gridPadding.bottom,max:this._gridPadding.top});this.target.append(this.grid.createElement(this._gridPadding,this));this.grid.draw();var aq=this.series;var aJ=aq.length;for(aH=0,aE=aJ;aHax)?av:ax;var ar=this.series[aw];var aq=this.series[au];if(aq.renderer.smooth){var ap=aq.renderer._smoothedData.slice(0).reverse()}else{var ap=aq.gridData.slice(0).reverse()}if(ar.renderer.smooth){var at=ar.renderer._smoothedData.concat(ap)}else{var at=ar.gridData.concat(ap)}var ao=(an.color!==null)?an.color:this.series[ax].fillColor;var ay=(an.baseSeries!==null)?an.baseSeries:aw;var am=this.series[ay].renderer.shapeRenderer;var al={fillStyle:ao,fill:true,closePath:true};am.draw(ar.shadowCanvas._ctx,at,al)};this.bindCustomEvents=function(){this.eventCanvas._elem.bind("click",{plot:this},this.onClick);this.eventCanvas._elem.bind("dblclick",{plot:this},this.onDblClick);this.eventCanvas._elem.bind("mousedown",{plot:this},this.onMouseDown);this.eventCanvas._elem.bind("mousemove",{plot:this},this.onMouseMove);this.eventCanvas._elem.bind("mouseenter",{plot:this},this.onMouseEnter);this.eventCanvas._elem.bind("mouseleave",{plot:this},this.onMouseLeave);if(this.captureRightClick){this.eventCanvas._elem.bind("mouseup",{plot:this},this.onRightClick);this.eventCanvas._elem.get(0).oncontextmenu=function(){return false}}else{this.eventCanvas._elem.bind("mouseup",{plot:this},this.onMouseUp)}};function ai(av){var au=av.data.plot;var ap=au.eventCanvas._elem.offset();var at={x:av.pageX-ap.left,y:av.pageY-ap.top};var aq={xaxis:null,yaxis:null,x2axis:null,y2axis:null,y3axis:null,y4axis:null,y5axis:null,y6axis:null,y7axis:null,y8axis:null,y9axis:null,yMidAxis:null};var ar=["xaxis","yaxis","x2axis","y2axis","y3axis","y4axis","y5axis","y6axis","y7axis","y8axis","y9axis","yMidAxis"];var al=au.axes;var am,ao;for(am=11;am>0;am--){ao=ar[am-1];if(al[ao].show){aq[ao]=al[ao].series_p2u(at[ao.charAt(0)])}}return{offsets:ap,gridPos:at,dataPos:aq}}function ak(al,am){var aq=am.series;var aW,aU,aT,aO,aP,aJ,aI,aw,au,az,aA,aK;var aS,aX,aQ,ar,aH,aM,aV;var an,aN;for(aT=am.seriesStack.length-1;aT>=0;aT--){aW=am.seriesStack[aT];aO=aq[aW];aV=aO._highlightThreshold;switch(aO.renderer.constructor){case L.jqplot.BarRenderer:aJ=al.x;aI=al.y;for(aU=0;aUaH[0][0]&&aJaH[2][1]&&aIaH[0][0]+aV[0][0]&&aJaH[2][1]&&aI0&&-aI>=0){aw=2*Math.PI-Math.atan(-aI/aJ)}else{if(aJ>0&&-aI<0){aw=-Math.atan(-aI/aJ)}else{if(aJ<0){aw=Math.PI-Math.atan(-aI/aJ)}else{if(aJ==0&&-aI>0){aw=3*Math.PI/2}else{if(aJ==0&&-aI<0){aw=Math.PI/2}else{if(aJ==0&&aI==0){aw=0}}}}}}if(az){aw-=az;if(aw<0){aw+=2*Math.PI}else{if(aw>2*Math.PI){aw-=2*Math.PI}}}au=aO.sliceMargin/180*Math.PI;if(aPaO._innerRadius){for(aU=0;aU0)?aO.gridData[aU-1][1]+au:au;aK=aO.gridData[aU][1];if(aw>aA&&aw0&&-aI>=0){aw=2*Math.PI-Math.atan(-aI/aJ)}else{if(aJ>0&&-aI<0){aw=-Math.atan(-aI/aJ)}else{if(aJ<0){aw=Math.PI-Math.atan(-aI/aJ)}else{if(aJ==0&&-aI>0){aw=3*Math.PI/2}else{if(aJ==0&&-aI<0){aw=Math.PI/2}else{if(aJ==0&&aI==0){aw=0}}}}}}if(az){aw-=az;if(aw<0){aw+=2*Math.PI}else{if(aw>2*Math.PI){aw-=2*Math.PI}}}au=aO.sliceMargin/180*Math.PI;if(aP0)?aO.gridData[aU-1][1]+au:au;aK=aO.gridData[aU][1];if(aw>aA&&aw=ay[0][1]&&aI<=ay[3][1]&&aJ>=at[0]&&aJ<=aE[0]){return{seriesIndex:aO.index,pointIndex:aU,gridData:null,data:aO.data[aU]}}}break;case L.jqplot.LineRenderer:aJ=al.x;aI=al.y;aP=aO.renderer;if(aO.show){if((aO.fill||(aO.renderer.bands.show&&aO.renderer.bands.fill))&&(!am.plugins.highlighter||!am.plugins.highlighter.show)){var ax=false;if(aJ>aO._boundingBox[0][0]&&aJaO._boundingBox[1][1]&&aI=aI||aB[1]=aI){if(aC[0]+(aI-aC[1])/(aB[1]-aC[1])*(aB[0]-aC[0])0)?aN:0;for(var aU=0;aU=aQ[0]-aP._bodyWidth/2&&aJ<=aQ[0]+aP._bodyWidth/2&&aI>=av(aO.data[aU][2])&&aI<=av(aO.data[aU][3])){return{seriesIndex:aW,pointIndex:aU,gridData:aQ,data:aO.data[aU]}}}else{if(!aP.hlc){var av=aO._yaxis.series_u2p;if(aJ>=aQ[0]-aP._tickLength&&aJ<=aQ[0]+aP._tickLength&&aI>=av(aO.data[aU][2])&&aI<=av(aO.data[aU][3])){return{seriesIndex:aW,pointIndex:aU,gridData:aQ,data:aO.data[aU]}}}else{var av=aO._yaxis.series_u2p;if(aJ>=aQ[0]-aP._tickLength&&aJ<=aQ[0]+aP._tickLength&&aI>=av(aO.data[aU][1])&&aI<=av(aO.data[aU][2])){return{seriesIndex:aW,pointIndex:aU,gridData:aQ,data:aO.data[aU]}}}}}else{if(aQ[0]!=null&&aQ[1]!=null){aX=Math.sqrt((aJ-aQ[0])*(aJ-aQ[0])+(aI-aQ[1])*(aI-aQ[1]));if(aX<=an&&(aX<=aS||aS==null)){aS=aX;return{seriesIndex:aW,pointIndex:aU,gridData:aQ,data:aO.data[aU]}}}}}}}break;default:aJ=al.x;aI=al.y;aP=aO.renderer;if(aO.show){aN=aO.markerRenderer.size/2+aO.neighborThreshold;an=(aN>0)?aN:0;for(var aU=0;aU=aQ[0]-aP._bodyWidth/2&&aJ<=aQ[0]+aP._bodyWidth/2&&aI>=av(aO.data[aU][2])&&aI<=av(aO.data[aU][3])){return{seriesIndex:aW,pointIndex:aU,gridData:aQ,data:aO.data[aU]}}}else{if(!aP.hlc){var av=aO._yaxis.series_u2p;if(aJ>=aQ[0]-aP._tickLength&&aJ<=aQ[0]+aP._tickLength&&aI>=av(aO.data[aU][2])&&aI<=av(aO.data[aU][3])){return{seriesIndex:aW,pointIndex:aU,gridData:aQ,data:aO.data[aU]}}}else{var av=aO._yaxis.series_u2p;if(aJ>=aQ[0]-aP._tickLength&&aJ<=aQ[0]+aP._tickLength&&aI>=av(aO.data[aU][1])&&aI<=av(aO.data[aU][2])){return{seriesIndex:aW,pointIndex:aU,gridData:aQ,data:aO.data[aU]}}}}}else{aX=Math.sqrt((aJ-aQ[0])*(aJ-aQ[0])+(aI-aQ[1])*(aI-aQ[1]));if(aX<=an&&(aX<=aS||aS==null)){aS=aX;return{seriesIndex:aW,pointIndex:aU,gridData:aQ,data:aO.data[aU]}}}}}break}}return null}this.onClick=function(an){var am=ai(an);var ap=an.data.plot;var ao=ak(am.gridPos,ap);var al=L.Event("jqplotClick");al.pageX=an.pageX;al.pageY=an.pageY;L(this).trigger(al,[am.gridPos,am.dataPos,ao,ap])};this.onDblClick=function(an){var am=ai(an);var ap=an.data.plot;var ao=ak(am.gridPos,ap);var al=L.Event("jqplotDblClick");al.pageX=an.pageX;al.pageY=an.pageY;L(this).trigger(al,[am.gridPos,am.dataPos,ao,ap])};this.onMouseDown=function(an){var am=ai(an);var ap=an.data.plot;var ao=ak(am.gridPos,ap);var al=L.Event("jqplotMouseDown");al.pageX=an.pageX;al.pageY=an.pageY;L(this).trigger(al,[am.gridPos,am.dataPos,ao,ap])};this.onMouseUp=function(an){var am=ai(an);var al=L.Event("jqplotMouseUp");al.pageX=an.pageX;al.pageY=an.pageY;L(this).trigger(al,[am.gridPos,am.dataPos,null,an.data.plot])};this.onRightClick=function(an){var am=ai(an);var ap=an.data.plot;var ao=ak(am.gridPos,ap);if(ap.captureRightClick){if(an.which==3){var al=L.Event("jqplotRightClick");al.pageX=an.pageX;al.pageY=an.pageY;L(this).trigger(al,[am.gridPos,am.dataPos,ao,ap])}else{var al=L.Event("jqplotMouseUp");al.pageX=an.pageX;al.pageY=an.pageY;L(this).trigger(al,[am.gridPos,am.dataPos,ao,ap])}}};this.onMouseMove=function(an){var am=ai(an);var ap=an.data.plot;var ao=ak(am.gridPos,ap);var al=L.Event("jqplotMouseMove");al.pageX=an.pageX;al.pageY=an.pageY;L(this).trigger(al,[am.gridPos,am.dataPos,ao,ap])};this.onMouseEnter=function(an){var am=ai(an);var ao=an.data.plot;var al=L.Event("jqplotMouseEnter");al.pageX=an.pageX;al.pageY=an.pageY;al.relatedTarget=an.relatedTarget;L(this).trigger(al,[am.gridPos,am.dataPos,null,ao])};this.onMouseLeave=function(an){var am=ai(an);var ao=an.data.plot;var al=L.Event("jqplotMouseLeave");al.pageX=an.pageX;al.pageY=an.pageY;al.relatedTarget=an.relatedTarget;L(this).trigger(al,[am.gridPos,am.dataPos,null,ao])};this.drawSeries=function(an,al){var ap,ao,am;al=(typeof(an)==="number"&&al==null)?an:al;an=(typeof(an)==="object")?an:{};if(al!=u){ao=this.series[al];am=ao.shadowCanvas._ctx;am.clearRect(0,0,am.canvas.width,am.canvas.height);ao.drawShadow(am,an,this);am=ao.canvas._ctx;am.clearRect(0,0,am.canvas.width,am.canvas.height);ao.draw(am,an,this);if(ao.renderer.constructor==L.jqplot.BezierCurveRenderer){if(al660)?ah[aj]*0.85:0.73*ah[aj]+90;ah[aj]=parseInt(ah[aj],10);(ah[aj]>255)?255:ah[aj]}ah[3]=0.3+0.35*al[3];ak.push("rgba("+ah[0]+","+ah[1]+","+ah[2]+","+ah[3]+")")}}else{var al=L.jqplot.getColorComponents(ai);var ah=[al[0],al[1],al[2]];var an=ah[0]+ah[1]+ah[2];for(var aj=0;aj<3;aj++){ah[aj]=(an>660)?ah[aj]*0.85:0.73*ah[aj]+90;ah[aj]=parseInt(ah[aj],10);(ah[aj]>255)?255:ah[aj]}ah[3]=0.3+0.35*al[3];ak="rgba("+ah[0]+","+ah[1]+","+ah[2]+","+ah[3]+")"}return ak};L.jqplot.ColorGenerator=function(ai){ai=ai||L.jqplot.config.defaultColors;var ah=0;this.next=function(){if(ah0){return ai[ah--]}else{ah=ai.length-1;return ai[ah]}};this.get=function(ak){var aj=ak-ai.length*Math.floor(ak/ai.length);return ai[aj]};this.setColors=function(aj){ai=aj};this.reset=function(){ah=0};this.getIndex=function(){return ah};this.setIndex=function(aj){ah=aj}};L.jqplot.hex2rgb=function(aj,ah){aj=aj.replace("#","");if(aj.length==3){aj=aj.charAt(0)+aj.charAt(0)+aj.charAt(1)+aj.charAt(1)+aj.charAt(2)+aj.charAt(2)}var ai;ai="rgba("+parseInt(aj.slice(0,2),16)+", "+parseInt(aj.slice(2,4),16)+", "+parseInt(aj.slice(4,6),16);if(ah){ai+=", "+ah}ai+=")";return ai};L.jqplot.rgb2hex=function(am){var aj=/rgba?\( *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *(?:, *[0-9.]*)?\)/;var ah=am.match(aj);var al="#";for(var ak=1;ak<4;ak++){var ai;if(ah[ak].search(/%/)!=-1){ai=parseInt(255*ah[ak]/100,10).toString(16);if(ai.length==1){ai="0"+ai}}else{ai=parseInt(ah[ak],10).toString(16);if(ai.length==1){ai="0"+ai}}al+=ai}return al};L.jqplot.normalize2rgb=function(ai,ah){if(ai.search(/^ *rgba?\(/)!=-1){return ai}else{if(ai.search(/^ *#?[0-9a-fA-F]?[0-9a-fA-F]/)!=-1){return L.jqplot.hex2rgb(ai,ah)}else{throw new Error("Invalid color spec")}}};L.jqplot.getColorComponents=function(am){am=L.jqplot.colorKeywordMap[am]||am;var ak=L.jqplot.normalize2rgb(am);var aj=/rgba?\( *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *,? *([0-9.]* *)?\)/;var ah=ak.match(aj);var ai=[];for(var al=1;al<4;al++){if(ah[al].search(/%/)!=-1){ai[al-1]=parseInt(255*ah[al]/100,10)}else{ai[al-1]=parseInt(ah[al],10)}}ai[3]=parseFloat(ah[4])?parseFloat(ah[4]):1;return ai};L.jqplot.colorKeywordMap={aliceblue:"rgb(240, 248, 255)",antiquewhite:"rgb(250, 235, 215)",aqua:"rgb( 0, 255, 255)",aquamarine:"rgb(127, 255, 212)",azure:"rgb(240, 255, 255)",beige:"rgb(245, 245, 220)",bisque:"rgb(255, 228, 196)",black:"rgb( 0, 0, 0)",blanchedalmond:"rgb(255, 235, 205)",blue:"rgb( 0, 0, 255)",blueviolet:"rgb(138, 43, 226)",brown:"rgb(165, 42, 42)",burlywood:"rgb(222, 184, 135)",cadetblue:"rgb( 95, 158, 160)",chartreuse:"rgb(127, 255, 0)",chocolate:"rgb(210, 105, 30)",coral:"rgb(255, 127, 80)",cornflowerblue:"rgb(100, 149, 237)",cornsilk:"rgb(255, 248, 220)",crimson:"rgb(220, 20, 60)",cyan:"rgb( 0, 255, 255)",darkblue:"rgb( 0, 0, 139)",darkcyan:"rgb( 0, 139, 139)",darkgoldenrod:"rgb(184, 134, 11)",darkgray:"rgb(169, 169, 169)",darkgreen:"rgb( 0, 100, 0)",darkgrey:"rgb(169, 169, 169)",darkkhaki:"rgb(189, 183, 107)",darkmagenta:"rgb(139, 0, 139)",darkolivegreen:"rgb( 85, 107, 47)",darkorange:"rgb(255, 140, 0)",darkorchid:"rgb(153, 50, 204)",darkred:"rgb(139, 0, 0)",darksalmon:"rgb(233, 150, 122)",darkseagreen:"rgb(143, 188, 143)",darkslateblue:"rgb( 72, 61, 139)",darkslategray:"rgb( 47, 79, 79)",darkslategrey:"rgb( 47, 79, 79)",darkturquoise:"rgb( 0, 206, 209)",darkviolet:"rgb(148, 0, 211)",deeppink:"rgb(255, 20, 147)",deepskyblue:"rgb( 0, 191, 255)",dimgray:"rgb(105, 105, 105)",dimgrey:"rgb(105, 105, 105)",dodgerblue:"rgb( 30, 144, 255)",firebrick:"rgb(178, 34, 34)",floralwhite:"rgb(255, 250, 240)",forestgreen:"rgb( 34, 139, 34)",fuchsia:"rgb(255, 0, 255)",gainsboro:"rgb(220, 220, 220)",ghostwhite:"rgb(248, 248, 255)",gold:"rgb(255, 215, 0)",goldenrod:"rgb(218, 165, 32)",gray:"rgb(128, 128, 128)",grey:"rgb(128, 128, 128)",green:"rgb( 0, 128, 0)",greenyellow:"rgb(173, 255, 47)",honeydew:"rgb(240, 255, 240)",hotpink:"rgb(255, 105, 180)",indianred:"rgb(205, 92, 92)",indigo:"rgb( 75, 0, 130)",ivory:"rgb(255, 255, 240)",khaki:"rgb(240, 230, 140)",lavender:"rgb(230, 230, 250)",lavenderblush:"rgb(255, 240, 245)",lawngreen:"rgb(124, 252, 0)",lemonchiffon:"rgb(255, 250, 205)",lightblue:"rgb(173, 216, 230)",lightcoral:"rgb(240, 128, 128)",lightcyan:"rgb(224, 255, 255)",lightgoldenrodyellow:"rgb(250, 250, 210)",lightgray:"rgb(211, 211, 211)",lightgreen:"rgb(144, 238, 144)",lightgrey:"rgb(211, 211, 211)",lightpink:"rgb(255, 182, 193)",lightsalmon:"rgb(255, 160, 122)",lightseagreen:"rgb( 32, 178, 170)",lightskyblue:"rgb(135, 206, 250)",lightslategray:"rgb(119, 136, 153)",lightslategrey:"rgb(119, 136, 153)",lightsteelblue:"rgb(176, 196, 222)",lightyellow:"rgb(255, 255, 224)",lime:"rgb( 0, 255, 0)",limegreen:"rgb( 50, 205, 50)",linen:"rgb(250, 240, 230)",magenta:"rgb(255, 0, 255)",maroon:"rgb(128, 0, 0)",mediumaquamarine:"rgb(102, 205, 170)",mediumblue:"rgb( 0, 0, 205)",mediumorchid:"rgb(186, 85, 211)",mediumpurple:"rgb(147, 112, 219)",mediumseagreen:"rgb( 60, 179, 113)",mediumslateblue:"rgb(123, 104, 238)",mediumspringgreen:"rgb( 0, 250, 154)",mediumturquoise:"rgb( 72, 209, 204)",mediumvioletred:"rgb(199, 21, 133)",midnightblue:"rgb( 25, 25, 112)",mintcream:"rgb(245, 255, 250)",mistyrose:"rgb(255, 228, 225)",moccasin:"rgb(255, 228, 181)",navajowhite:"rgb(255, 222, 173)",navy:"rgb( 0, 0, 128)",oldlace:"rgb(253, 245, 230)",olive:"rgb(128, 128, 0)",olivedrab:"rgb(107, 142, 35)",orange:"rgb(255, 165, 0)",orangered:"rgb(255, 69, 0)",orchid:"rgb(218, 112, 214)",palegoldenrod:"rgb(238, 232, 170)",palegreen:"rgb(152, 251, 152)",paleturquoise:"rgb(175, 238, 238)",palevioletred:"rgb(219, 112, 147)",papayawhip:"rgb(255, 239, 213)",peachpuff:"rgb(255, 218, 185)",peru:"rgb(205, 133, 63)",pink:"rgb(255, 192, 203)",plum:"rgb(221, 160, 221)",powderblue:"rgb(176, 224, 230)",purple:"rgb(128, 0, 128)",red:"rgb(255, 0, 0)",rosybrown:"rgb(188, 143, 143)",royalblue:"rgb( 65, 105, 225)",saddlebrown:"rgb(139, 69, 19)",salmon:"rgb(250, 128, 114)",sandybrown:"rgb(244, 164, 96)",seagreen:"rgb( 46, 139, 87)",seashell:"rgb(255, 245, 238)",sienna:"rgb(160, 82, 45)",silver:"rgb(192, 192, 192)",skyblue:"rgb(135, 206, 235)",slateblue:"rgb(106, 90, 205)",slategray:"rgb(112, 128, 144)",slategrey:"rgb(112, 128, 144)",snow:"rgb(255, 250, 250)",springgreen:"rgb( 0, 255, 127)",steelblue:"rgb( 70, 130, 180)",tan:"rgb(210, 180, 140)",teal:"rgb( 0, 128, 128)",thistle:"rgb(216, 191, 216)",tomato:"rgb(255, 99, 71)",turquoise:"rgb( 64, 224, 208)",violet:"rgb(238, 130, 238)",wheat:"rgb(245, 222, 179)",white:"rgb(255, 255, 255)",whitesmoke:"rgb(245, 245, 245)",yellow:"rgb(255, 255, 0)",yellowgreen:"rgb(154, 205, 50)"};L.jqplot.AxisLabelRenderer=function(ah){L.jqplot.ElemContainer.call(this);this.axis;this.show=true;this.label="";this.fontFamily=null;this.fontSize=null;this.textColor=null;this._elem;this.escapeHTML=false;L.extend(true,this,ah)};L.jqplot.AxisLabelRenderer.prototype=new L.jqplot.ElemContainer();L.jqplot.AxisLabelRenderer.prototype.constructor=L.jqplot.AxisLabelRenderer;L.jqplot.AxisLabelRenderer.prototype.init=function(ah){L.extend(true,this,ah)};L.jqplot.AxisLabelRenderer.prototype.draw=function(ah,ai){if(this._elem){this._elem.emptyForce();this._elem=null}this._elem=L('
');if(Number(this.label)){this._elem.css("white-space","nowrap")}if(!this.escapeHTML){this._elem.html(this.label)}else{this._elem.text(this.label)}if(this.fontFamily){this._elem.css("font-family",this.fontFamily)}if(this.fontSize){this._elem.css("font-size",this.fontSize)}if(this.textColor){this._elem.css("color",this.textColor)}return this._elem};L.jqplot.AxisLabelRenderer.prototype.pack=function(){};L.jqplot.AxisTickRenderer=function(ah){L.jqplot.ElemContainer.call(this);this.mark="outside";this.axis;this.showMark=true;this.showGridline=true;this.isMinorTick=false;this.size=4;this.markSize=6;this.show=true;this.showLabel=true;this.label=null;this.value=null;this._styles={};this.formatter=L.jqplot.DefaultTickFormatter;this.prefix="";this.suffix="";this.formatString="";this.fontFamily;this.fontSize;this.textColor;this.escapeHTML=false;this._elem;this._breakTick=false;L.extend(true,this,ah)};L.jqplot.AxisTickRenderer.prototype.init=function(ah){L.extend(true,this,ah)};L.jqplot.AxisTickRenderer.prototype=new L.jqplot.ElemContainer();L.jqplot.AxisTickRenderer.prototype.constructor=L.jqplot.AxisTickRenderer;L.jqplot.AxisTickRenderer.prototype.setTick=function(ah,aj,ai){this.value=ah;this.axis=aj;if(ai){this.isMinorTick=true}return this};L.jqplot.AxisTickRenderer.prototype.draw=function(){if(this.label===null){this.label=this.prefix+this.formatter(this.formatString,this.value)+this.suffix}var ai={position:"absolute"};if(Number(this.label)){ai.whitSpace="nowrap"}if(this._elem){this._elem.emptyForce();this._elem=null}this._elem=L(document.createElement("div"));this._elem.addClass("jqplot-"+this.axis+"-tick");if(!this.escapeHTML){this._elem.html(this.label)}else{this._elem.text(this.label)}this._elem.css(ai);for(var ah in this._styles){this._elem.css(ah,this._styles[ah])}if(this.fontFamily){this._elem.css("font-family",this.fontFamily)}if(this.fontSize){this._elem.css("font-size",this.fontSize)}if(this.textColor){this._elem.css("color",this.textColor)}if(this._breakTick){this._elem.addClass("jqplot-breakTick")}return this._elem};L.jqplot.DefaultTickFormatter=function(ah,ai){if(typeof ai=="number"){if(!ah){ah=L.jqplot.config.defaultTickFormatString}return L.jqplot.sprintf(ah,ai)}else{return String(ai)}};L.jqplot.PercentTickFormatter=function(ah,ai){if(typeof ai=="number"){ai=100*ai;if(!ah){ah=L.jqplot.config.defaultTickFormatString}return L.jqplot.sprintf(ah,ai)}else{return String(ai)}};L.jqplot.AxisTickRenderer.prototype.pack=function(){};L.jqplot.CanvasGridRenderer=function(){this.shadowRenderer=new L.jqplot.ShadowRenderer()};L.jqplot.CanvasGridRenderer.prototype.init=function(ai){this._ctx;L.extend(true,this,ai);var ah={lineJoin:"miter",lineCap:"round",fill:false,isarc:false,angle:this.shadowAngle,offset:this.shadowOffset,alpha:this.shadowAlpha,depth:this.shadowDepth,lineWidth:this.shadowWidth,closePath:false,strokeStyle:this.shadowColor};this.renderer.shadowRenderer.init(ah)};L.jqplot.CanvasGridRenderer.prototype.createElement=function(ak){var aj;if(this._elem){if(L.jqplot.use_excanvas&&window.G_vmlCanvasManager.uninitElement!==u){aj=this._elem.get(0);window.G_vmlCanvasManager.uninitElement(aj);aj=null}this._elem.emptyForce();this._elem=null}aj=ak.canvasManager.getCanvas();var ah=this._plotDimensions.width;var ai=this._plotDimensions.height;aj.width=ah;aj.height=ai;this._elem=L(aj);this._elem.addClass("jqplot-grid-canvas");this._elem.css({position:"absolute",left:0,top:0});aj=ak.canvasManager.initCanvas(aj);this._top=this._offsets.top;this._bottom=ai-this._offsets.bottom;this._left=this._offsets.left;this._right=ah-this._offsets.right;this._width=this._right-this._left;this._height=this._bottom-this._top;aj=null;return this._elem};L.jqplot.CanvasGridRenderer.prototype.draw=function(){this._ctx=this._elem.get(0).getContext("2d");var at=this._ctx;var aw=this._axes;at.save();at.clearRect(0,0,this._plotDimensions.width,this._plotDimensions.height);at.fillStyle=this.backgroundColor||this.background;at.fillRect(this._left,this._top,this._width,this._height);at.save();at.lineJoin="miter";at.lineCap="butt";at.lineWidth=this.gridLineWidth;at.strokeStyle=this.gridLineColor;var aA,az,ap,aq;var am=["xaxis","yaxis","x2axis","y2axis"];for(var ay=4;ay>0;ay--){var aD=am[ay-1];var ah=aw[aD];var aB=ah._ticks;var ar=aB.length;if(ah.show){if(ah.drawBaseline){var aC={};if(ah.baselineWidth!==null){aC.lineWidth=ah.baselineWidth}if(ah.baselineColor!==null){aC.strokeStyle=ah.baselineColor}switch(aD){case"xaxis":ao(this._left,this._bottom,this._right,this._bottom,aC);break;case"yaxis":ao(this._left,this._bottom,this._left,this._top,aC);break;case"x2axis":ao(this._left,this._bottom,this._right,this._bottom,aC);break;case"y2axis":ao(this._right,this._bottom,this._right,this._top,aC);break}}for(var au=ar;au>0;au--){var an=aB[au-1];if(an.show){var ak=Math.round(ah.u2p(an.value))+0.5;switch(aD){case"xaxis":if(an.showGridline&&this.drawGridlines&&((!an.isMinorTick&&ah.drawMajorGridlines)||(an.isMinorTick&&ah.drawMinorGridlines))){ao(ak,this._top,ak,this._bottom)}if(an.showMark&&an.mark&&((!an.isMinorTick&&ah.drawMajorTickMarks)||(an.isMinorTick&&ah.drawMinorTickMarks))){ap=an.markSize;aq=an.mark;var ak=Math.round(ah.u2p(an.value))+0.5;switch(aq){case"outside":aA=this._bottom;az=this._bottom+ap;break;case"inside":aA=this._bottom-ap;az=this._bottom;break;case"cross":aA=this._bottom-ap;az=this._bottom+ap;break;default:aA=this._bottom;az=this._bottom+ap;break}if(this.shadow){this.renderer.shadowRenderer.draw(at,[[ak,aA],[ak,az]],{lineCap:"butt",lineWidth:this.gridLineWidth,offset:this.gridLineWidth*0.75,depth:2,fill:false,closePath:false})}ao(ak,aA,ak,az)}break;case"yaxis":if(an.showGridline&&this.drawGridlines&&((!an.isMinorTick&&ah.drawMajorGridlines)||(an.isMinorTick&&ah.drawMinorGridlines))){ao(this._right,ak,this._left,ak)}if(an.showMark&&an.mark&&((!an.isMinorTick&&ah.drawMajorTickMarks)||(an.isMinorTick&&ah.drawMinorTickMarks))){ap=an.markSize;aq=an.mark;var ak=Math.round(ah.u2p(an.value))+0.5;switch(aq){case"outside":aA=this._left-ap;az=this._left;break;case"inside":aA=this._left;az=this._left+ap;break;case"cross":aA=this._left-ap;az=this._left+ap;break;default:aA=this._left-ap;az=this._left;break}if(this.shadow){this.renderer.shadowRenderer.draw(at,[[aA,ak],[az,ak]],{lineCap:"butt",lineWidth:this.gridLineWidth*1.5,offset:this.gridLineWidth*0.75,fill:false,closePath:false})}ao(aA,ak,az,ak,{strokeStyle:ah.borderColor})}break;case"x2axis":if(an.showGridline&&this.drawGridlines&&((!an.isMinorTick&&ah.drawMajorGridlines)||(an.isMinorTick&&ah.drawMinorGridlines))){ao(ak,this._bottom,ak,this._top)}if(an.showMark&&an.mark&&((!an.isMinorTick&&ah.drawMajorTickMarks)||(an.isMinorTick&&ah.drawMinorTickMarks))){ap=an.markSize;aq=an.mark;var ak=Math.round(ah.u2p(an.value))+0.5;switch(aq){case"outside":aA=this._top-ap;az=this._top;break;case"inside":aA=this._top;az=this._top+ap;break;case"cross":aA=this._top-ap;az=this._top+ap;break;default:aA=this._top-ap;az=this._top;break}if(this.shadow){this.renderer.shadowRenderer.draw(at,[[ak,aA],[ak,az]],{lineCap:"butt",lineWidth:this.gridLineWidth,offset:this.gridLineWidth*0.75,depth:2,fill:false,closePath:false})}ao(ak,aA,ak,az)}break;case"y2axis":if(an.showGridline&&this.drawGridlines&&((!an.isMinorTick&&ah.drawMajorGridlines)||(an.isMinorTick&&ah.drawMinorGridlines))){ao(this._left,ak,this._right,ak)}if(an.showMark&&an.mark&&((!an.isMinorTick&&ah.drawMajorTickMarks)||(an.isMinorTick&&ah.drawMinorTickMarks))){ap=an.markSize;aq=an.mark;var ak=Math.round(ah.u2p(an.value))+0.5;switch(aq){case"outside":aA=this._right;az=this._right+ap;break;case"inside":aA=this._right-ap;az=this._right;break;case"cross":aA=this._right-ap;az=this._right+ap;break;default:aA=this._right;az=this._right+ap;break}if(this.shadow){this.renderer.shadowRenderer.draw(at,[[aA,ak],[az,ak]],{lineCap:"butt",lineWidth:this.gridLineWidth*1.5,offset:this.gridLineWidth*0.75,fill:false,closePath:false})}ao(aA,ak,az,ak,{strokeStyle:ah.borderColor})}break;default:break}}}an=null}ah=null;aB=null}am=["y3axis","y4axis","y5axis","y6axis","y7axis","y8axis","y9axis","yMidAxis"];for(var ay=7;ay>0;ay--){var ah=aw[am[ay-1]];var aB=ah._ticks;if(ah.show){var ai=aB[ah.numberTicks-1];var al=aB[0];var aj=ah.getLeft();var av=[[aj,ai.getTop()+ai.getHeight()/2],[aj,al.getTop()+al.getHeight()/2+1]];if(this.shadow){this.renderer.shadowRenderer.draw(at,av,{lineCap:"butt",fill:false,closePath:false})}ao(av[0][0],av[0][1],av[1][0],av[1][1],{lineCap:"butt",strokeStyle:ah.borderColor,lineWidth:ah.borderWidth});for(var au=aB.length;au>0;au--){var an=aB[au-1];ap=an.markSize;aq=an.mark;var ak=Math.round(ah.u2p(an.value))+0.5;if(an.showMark&&an.mark){switch(aq){case"outside":aA=aj;az=aj+ap;break;case"inside":aA=aj-ap;az=aj;break;case"cross":aA=aj-ap;az=aj+ap;break;default:aA=aj;az=aj+ap;break}av=[[aA,ak],[az,ak]];if(this.shadow){this.renderer.shadowRenderer.draw(at,av,{lineCap:"butt",lineWidth:this.gridLineWidth*1.5,offset:this.gridLineWidth*0.75,fill:false,closePath:false})}ao(aA,ak,az,ak,{strokeStyle:ah.borderColor})}an=null}al=null}ah=null;aB=null}at.restore();function ao(aH,aG,aE,ax,aF){at.save();aF=aF||{};if(aF.lineWidth==null||aF.lineWidth!=0){L.extend(true,at,aF);at.beginPath();at.moveTo(aH,aG);at.lineTo(aE,ax);at.stroke();at.restore()}}if(this.shadow){var av=[[this._left,this._bottom],[this._right,this._bottom],[this._right,this._top]];this.renderer.shadowRenderer.draw(at,av)}if(this.borderWidth!=0&&this.drawBorder){ao(this._left,this._top,this._right,this._top,{lineCap:"round",strokeStyle:aw.x2axis.borderColor,lineWidth:aw.x2axis.borderWidth});ao(this._right,this._top,this._right,this._bottom,{lineCap:"round",strokeStyle:aw.y2axis.borderColor,lineWidth:aw.y2axis.borderWidth});ao(this._right,this._bottom,this._left,this._bottom,{lineCap:"round",strokeStyle:aw.xaxis.borderColor,lineWidth:aw.xaxis.borderWidth});ao(this._left,this._bottom,this._left,this._top,{lineCap:"round",strokeStyle:aw.yaxis.borderColor,lineWidth:aw.yaxis.borderWidth})}at.restore();at=null;aw=null};L.jqplot.DivTitleRenderer=function(){};L.jqplot.DivTitleRenderer.prototype.init=function(ah){L.extend(true,this,ah)};L.jqplot.DivTitleRenderer.prototype.draw=function(){if(this._elem){this._elem.emptyForce();this._elem=null}var ak=this.renderer;var aj=document.createElement("div");this._elem=L(aj);this._elem.addClass("jqplot-title");if(!this.text){this.show=false;this._elem.height(0);this._elem.width(0)}else{if(this.text){var ah;if(this.color){ah=this.color}else{if(this.textColor){ah=this.textColor}}var ai={position:"absolute",top:"0px",left:"0px"};if(this._plotWidth){ai.width=this._plotWidth+"px"}if(this.fontSize){ai.fontSize=this.fontSize}if(typeof this.textAlign==="string"){ai.textAlign=this.textAlign}else{ai.textAlign="center"}if(ah){ai.color=ah}if(this.paddingBottom){ai.paddingBottom=this.paddingBottom}if(this.fontFamily){ai.fontFamily=this.fontFamily}this._elem.css(ai);if(this.escapeHtml){this._elem.text(this.text)}else{this._elem.html(this.text)}}}aj=null;return this._elem};L.jqplot.DivTitleRenderer.prototype.pack=function(){};var r=0.1;L.jqplot.LinePattern=function(aw,aq){var ap={dotted:[r,L.jqplot.config.dotGapLength],dashed:[L.jqplot.config.dashLength,L.jqplot.config.gapLength],solid:null};if(typeof aq==="string"){if(aq[0]==="."||aq[0]==="-"){var ax=aq;aq=[];for(var ao=0,al=ax.length;ao0)&&(aC>0)){aA/=aB;az/=aB;while(true){var aD=aC*ar;if(aD=aq.length){ak=0}ar=aq[ak]}else{au=ay;at=aE;if((ak&1)==0){aw.lineTo(au,at)}else{aw.moveTo(au,at)}ar-=aB/aC;break}}}};var ai=function(){aw.beginPath()};var am=function(){aj(an,ah)};return{moveTo:av,lineTo:aj,beginPath:ai,closePath:am}};L.jqplot.LineRenderer=function(){this.shapeRenderer=new L.jqplot.ShapeRenderer();this.shadowRenderer=new L.jqplot.ShadowRenderer()};L.jqplot.LineRenderer.prototype.init=function(ai,an){ai=ai||{};this._type="line";this.renderer.animation={show:false,direction:"left",speed:2500,_supported:true};this.renderer.smooth=false;this.renderer.tension=null;this.renderer.constrainSmoothing=true;this.renderer._smoothedData=[];this.renderer._smoothedPlotData=[];this.renderer._hiBandGridData=[];this.renderer._lowBandGridData=[];this.renderer._hiBandSmoothedData=[];this.renderer._lowBandSmoothedData=[];this.renderer.bandData=[];this.renderer.bands={show:false,hiData:[],lowData:[],color:this.color,showLines:false,fill:true,fillColor:null,_min:null,_max:null,interval:"3%"};var al={highlightMouseOver:ai.highlightMouseOver,highlightMouseDown:ai.highlightMouseDown,highlightColor:ai.highlightColor};delete (ai.highlightMouseOver);delete (ai.highlightMouseDown);delete (ai.highlightColor);L.extend(true,this.renderer,ai);this.renderer.options=ai;if(this.renderer.bandData.length>1&&(!ai.bands||ai.bands.show==null)){this.renderer.bands.show=true}else{if(ai.bands&&ai.bands.show==null&&ai.bands.interval!=null){this.renderer.bands.show=true}}if(this.fill){this.renderer.bands.show=false}if(this.renderer.bands.show){this.renderer.initBands.call(this,this.renderer.options,an)}if(this._stack){this.renderer.smooth=false}var am={lineJoin:this.lineJoin,lineCap:this.lineCap,fill:this.fill,isarc:false,strokeStyle:this.color,fillStyle:this.fillColor,lineWidth:this.lineWidth,linePattern:this.linePattern,closePath:this.fill};this.renderer.shapeRenderer.init(am);var aj=ai.shadowOffset;if(aj==null){if(this.lineWidth>2.5){aj=1.25*(1+(Math.atan((this.lineWidth/2.5))/0.785398163-1)*0.6)}else{aj=1.25*Math.atan((this.lineWidth/2.5))/0.785398163}}var ah={lineJoin:this.lineJoin,lineCap:this.lineCap,fill:this.fill,isarc:false,angle:this.shadowAngle,offset:aj,alpha:this.shadowAlpha,depth:this.shadowDepth,lineWidth:this.lineWidth,linePattern:this.linePattern,closePath:this.fill};this.renderer.shadowRenderer.init(ah);this._areaPoints=[];this._boundingBox=[[],[]];if(!this.isTrendline&&this.fill||this.renderer.bands.show){this.highlightMouseOver=true;this.highlightMouseDown=false;this.highlightColor=null;if(al.highlightMouseDown&&al.highlightMouseOver==null){al.highlightMouseOver=false}L.extend(true,this,{highlightMouseOver:al.highlightMouseOver,highlightMouseDown:al.highlightMouseDown,highlightColor:al.highlightColor});if(!this.highlightColor){var ak=(this.renderer.bands.show)?this.renderer.bands.fillColor:this.fillColor;this.highlightColor=L.jqplot.computeHighlightColors(ak)}if(this.highlighter){this.highlighter.show=false}}if(!this.isTrendline&&an){an.plugins.lineRenderer={};an.postInitHooks.addOnce(z);an.postDrawHooks.addOnce(af);an.eventListenerHooks.addOnce("jqplotMouseMove",h);an.eventListenerHooks.addOnce("jqplotMouseDown",e);an.eventListenerHooks.addOnce("jqplotMouseUp",ad);an.eventListenerHooks.addOnce("jqplotClick",g);an.eventListenerHooks.addOnce("jqplotRightClick",s)}};L.jqplot.LineRenderer.prototype.initBands=function(ak,av){var al=ak.bandData||[];var an=this.renderer.bands;an.hiData=[];an.lowData=[];var aB=this.data;an._max=null;an._min=null;if(al.length==2){if(L.isArray(al[0][0])){var ao;var ah=0,ar=0;for(var aw=0,at=al[0].length;awan._max)||an._max==null){an._max=ao[1]}if((ao[1]!=null&&ao[1]an._max)||an._max==null){an._max=ao[1];ar=1}if((ao[1]!=null&&ao[1]al[1][0])?0:1;var aC=(aj)?0:1;for(var aw=0,at=aB.length;aw2&&!L.isArray(al[0][0])){var aj=(al[0][0]>al[0][1])?0:1;var aC=(aj)?0:1;for(var aw=0,at=al.length;awan._max)||an._max==null){an._max=am[aw][1]}}for(var aw=0,at=ap.length;aw0){aR=Math.abs((ap[aQ][1]-ap[aQ-1][1])/(ap[aQ][0]-ap[aQ-1][0]))}am=aR/aG+aE;aM=aF*A(am)-aF*A(aE)+aS;aT=(aO+aM)/2}else{aT=aU}for(aK=0;aK2){var ao;if(this.renderer.constrainSmoothing){ao=J.call(this,this.gridData);this.renderer._smoothedData=ao[0];this.renderer._smoothedPlotData=ao[1];if(ak.show){ao=J.call(this,this.renderer._hiBandGridData);this.renderer._hiBandSmoothedData=ao[0];ao=J.call(this,this.renderer._lowBandGridData);this.renderer._lowBandSmoothedData=ao[0]}ao=null}else{ao=F.call(this,this.gridData);this.renderer._smoothedData=ao[0];this.renderer._smoothedPlotData=ao[1];if(ak.show){ao=F.call(this,this.renderer._hiBandGridData);this.renderer._hiBandSmoothedData=ao[0];ao=F.call(this,this.renderer._lowBandGridData);this.renderer._lowBandSmoothedData=ao[0]}ao=null}}};L.jqplot.LineRenderer.prototype.makeGridData=function(ao,aq){var am=this._xaxis.series_u2p;var ah=this._yaxis.series_u2p;var ar=[];var aj=[];this.renderer._smoothedData=[];this.renderer._smoothedPlotData=[];this.renderer._hiBandGridData=[];this.renderer._lowBandGridData=[];this.renderer._hiBandSmoothedData=[];this.renderer._lowBandSmoothedData=[];var al=this.renderer.bands;var ai=false;for(var an=0;an2){var ap;if(this.renderer.constrainSmoothing){ap=J.call(this,ar);this.renderer._smoothedData=ap[0];this.renderer._smoothedPlotData=ap[1];if(al.show){ap=J.call(this,this.renderer._hiBandGridData);this.renderer._hiBandSmoothedData=ap[0];ap=J.call(this,this.renderer._lowBandGridData);this.renderer._lowBandSmoothedData=ap[0]}ap=null}else{ap=F.call(this,ar);this.renderer._smoothedData=ap[0];this.renderer._smoothedPlotData=ap[1];if(al.show){ap=F.call(this,this.renderer._hiBandGridData);this.renderer._hiBandSmoothedData=ap[0];ap=F.call(this,this.renderer._lowBandGridData);this.renderer._lowBandSmoothedData=ap[0]}ap=null}}return ar};L.jqplot.LineRenderer.prototype.draw=function(ax,aI,ai,aB){var aC;var aq=L.extend(true,{},ai);var ak=(aq.shadow!=u)?aq.shadow:this.shadow;var aJ=(aq.showLine!=u)?aq.showLine:this.showLine;var aA=(aq.fill!=u)?aq.fill:this.fill;var ah=(aq.fillAndStroke!=u)?aq.fillAndStroke:this.fillAndStroke;var ar,ay,av,aE;ax.save();if(aI.length){if(aJ){if(aA){if(this.fillToZero){var aF=this.negativeColor;if(!this.useNegativeColors){aF=aq.fillStyle}var ao=false;var ap=aq.fillStyle;if(ah){var aH=aI.slice(0)}if(this.index==0||!this._stack){var aw=[];var aL=(this.renderer.smooth)?this.renderer._smoothedPlotData:this._plotData;this._areaPoints=[];var aG=this._yaxis.series_u2p(this.fillToValue);var aj=this._xaxis.series_u2p(this.fillToValue);aq.closePath=true;if(this.fillAxis=="y"){aw.push([aI[0][0],aG]);this._areaPoints.push([aI[0][0],aG]);for(var aC=0;aC0;aC--){aI.push(au[aC-1])}if(ak){this.renderer.shadowRenderer.draw(ax,aI,aq)}this._areaPoints=aI;this.renderer.shapeRenderer.draw(ax,aI,aq)}}else{if(ah){var aH=aI.slice(0)}if(this.index==0||!this._stack){var al=ax.canvas.height;aI.unshift([aI[0][0],al]);var aD=aI.length;aI.push([aI[aD-1][0],al])}else{var au=this._prevGridData;for(var aC=au.length;aC>0;aC--){aI.push(au[aC-1])}}this._areaPoints=aI;if(ak){this.renderer.shadowRenderer.draw(ax,aI,aq)}this.renderer.shapeRenderer.draw(ax,aI,aq)}if(ah){var az=L.extend(true,{},aq,{fill:false,closePath:false});this.renderer.shapeRenderer.draw(ax,aH,az);if(this.markerRenderer.show){if(this.renderer.smooth){aH=this.gridData}for(aC=0;aCat[0]||ar==null){ar=at[0]}if(aEat[1]||ay==null){ay=at[1]}}if(this.type==="line"&&this.renderer.bands.show){aE=this._yaxis.series_u2p(this.renderer.bands._min);ay=this._yaxis.series_u2p(this.renderer.bands._max)}this._boundingBox=[[ar,aE],[av,ay]];if(this.markerRenderer.show&&!aA){if(this.renderer.smooth){aI=this.gridData}for(aC=0;aCao){ao=aj}}}al=null;am=null;if(ah){ai=this._label._elem.outerWidth(true);an=this._label._elem.outerHeight(true)}if(this.name=="xaxis"){ao=ao+an;this._elem.css({height:ao+"px",left:"0px",bottom:"0px"})}else{if(this.name=="x2axis"){ao=ao+an;this._elem.css({height:ao+"px",left:"0px",top:"0px"})}else{if(this.name=="yaxis"){ao=ao+ai;this._elem.css({width:ao+"px",left:"0px",top:"0px"});if(ah&&this._label.constructor==L.jqplot.AxisLabelRenderer){this._label._elem.css("width",ai+"px")}}else{ao=ao+ai;this._elem.css({width:ao+"px",right:"0px",top:"0px"});if(ah&&this._label.constructor==L.jqplot.AxisLabelRenderer){this._label._elem.css("width",ai+"px")}}}}}};L.jqplot.LinearAxisRenderer.prototype.createTicks=function(aj){var aT=this._ticks;var aK=this.ticks;var az=this.name;var aB=this._dataBounds;var ah=(this.name.charAt(0)==="x")?this._plotDimensions.width:this._plotDimensions.height;var an;var a6,aI;var ap,ao;var a4,a0;var aH=this.min;var a5=this.max;var aW=this.numberTicks;var ba=this.tickInterval;var am=30;this._scalefact=(Math.max(ah,am+1)-am)/300;if(aK.length){for(a0=0;a0this.breakPoints[0]&&aO[0]<=this.breakPoints[1]){aU.show=false;aU.showGridline=false;aU.label=aO[1]}else{aU.label=aO[1]}}}else{aU.label=aO[1]}aU.setTick(aO[0],this.name);this._ticks.push(aU)}else{if(L.isPlainObject(aO)){L.extend(true,aU,aO);aU.axis=this.name;this._ticks.push(aU)}else{aU.value=aO;if(this.breakPoints){if(aO==this.breakPoints[0]){aU.label=this.breakTickLabel;aU._breakTick=true;aU.showGridline=false;aU.showMark=false}else{if(aO>this.breakPoints[0]&&aO<=this.breakPoints[1]){aU.show=false;aU.showGridline=false}}}aU.setTick(aO,this.name);this._ticks.push(aU)}}}this.numberTicks=aK.length;this.min=this._ticks[0].value;this.max=this._ticks[this.numberTicks-1].value;this.tickInterval=(this.max-this.min)/(this.numberTicks-1)}else{if(az=="xaxis"||az=="x2axis"){ah=this._plotDimensions.width}else{ah=this._plotDimensions.height}var ax=this.numberTicks;if(this.alignTicks){if(this.name==="x2axis"&&aj.axes.xaxis.show){ax=aj.axes.xaxis.numberTicks}else{if(this.name.charAt(0)==="y"&&this.name!=="yaxis"&&this.name!=="yMidAxis"&&aj.axes.yaxis.show){ax=aj.axes.yaxis.numberTicks}}}a6=((this.min!=null)?this.min:aB.min);aI=((this.max!=null)?this.max:aB.max);var av=aI-a6;var aS,ay;var at;if(this.tickOptions==null||!this.tickOptions.formatString){this._overrideFormatString=true}if(this.min==null||this.max==null&&this.tickInterval==null&&!this.autoscale){if(this.forceTickAt0){if(a6>0){a6=0}if(aI<0){aI=0}}if(this.forceTickAt100){if(a6>100){a6=100}if(aI<100){aI=100}}var aE=false,a1=false;if(this.min!=null){aE=true}else{if(this.max!=null){a1=true}}var aP=L.jqplot.LinearTickGenerator(a6,aI,this._scalefact,ax,aE,a1);var aw=(this.min!=null)?a6:a6+av*(this.padMin-1);var aQ=(this.max!=null)?aI:aI-av*(this.padMax-1);if(a6aQ){aw=(this.min!=null)?a6:a6-av*(this.padMin-1);aQ=(this.max!=null)?aI:aI+av*(this.padMax-1);aP=L.jqplot.LinearTickGenerator(aw,aQ,this._scalefact,ax,aE,a1)}this.min=aP[0];this.max=aP[1];this.numberTicks=aP[2];this._autoFormatString=aP[3];this.tickInterval=aP[4]}else{if(a6==aI){var ai=0.05;if(a6>0){ai=Math.max(Math.log(a6)/Math.LN10,0.05)}a6-=ai;aI+=ai}if(this.autoscale&&this.min==null&&this.max==null){var ak,al,ar;var aC=false;var aN=false;var aA={min:null,max:null,average:null,stddev:null};for(var a0=0;a0a2){a2=aR[aZ]}}}var au=(a2-aG)/a2;if(aV.renderer.constructor==L.jqplot.BarRenderer){if(aG>=0&&(aV.fillToZero||au>0.1)){aC=true}else{aC=false;if(aV.fill&&aV.fillToZero&&aG<0&&a2>0){aN=true}else{aN=false}}}else{if(aV.fill){if(aG>=0&&(aV.fillToZero||au>0.1)){aC=true}else{if(aG<0&&a2>0&&aV.fillToZero){aC=false;aN=true}else{aC=false;aN=false}}}else{if(aG<0){aC=false}}}}}if(aC){this.numberTicks=2+Math.ceil((ah-(this.tickSpacing-1))/this.tickSpacing);this.min=0;aH=0;al=aI/(this.numberTicks-1);at=Math.pow(10,Math.abs(Math.floor(Math.log(al)/Math.LN10)));if(al/at==parseInt(al/at,10)){al+=at}this.tickInterval=Math.ceil(al/at)*at;this.max=this.tickInterval*(this.numberTicks-1)}else{if(aN){this.numberTicks=2+Math.ceil((ah-(this.tickSpacing-1))/this.tickSpacing);var aJ=Math.ceil(Math.abs(a6)/av*(this.numberTicks-1));var a9=this.numberTicks-1-aJ;al=Math.max(Math.abs(a6/aJ),Math.abs(aI/a9));at=Math.pow(10,Math.abs(Math.floor(Math.log(al)/Math.LN10)));this.tickInterval=Math.ceil(al/at)*at;this.max=this.tickInterval*a9;this.min=-this.tickInterval*aJ}else{if(this.numberTicks==null){if(this.tickInterval){this.numberTicks=3+Math.ceil(av/this.tickInterval)}else{this.numberTicks=2+Math.ceil((ah-(this.tickSpacing-1))/this.tickSpacing)}}if(this.tickInterval==null){al=av/(this.numberTicks-1);if(al<1){at=Math.pow(10,Math.abs(Math.floor(Math.log(al)/Math.LN10)))}else{at=1}this.tickInterval=Math.ceil(al*at*this.pad)/at}else{at=1/this.tickInterval}ak=this.tickInterval*(this.numberTicks-1);ar=(ak-av)/2;if(this.min==null){this.min=Math.floor(at*(a6-ar))/at}if(this.max==null){this.max=this.min+ak}}}var aF=L.jqplot.getSignificantFigures(this.tickInterval);var aM;if(aF.digitsLeft>=aF.significantDigits){aM="%d"}else{var at=Math.max(0,5-aF.digitsLeft);at=Math.min(at,aF.digitsRight);aM="%."+at+"f"}this._autoFormatString=aM}else{aS=(this.min!=null)?this.min:a6-av*(this.padMin-1);ay=(this.max!=null)?this.max:aI+av*(this.padMax-1);av=ay-aS;if(this.numberTicks==null){if(this.tickInterval!=null){this.numberTicks=Math.ceil((ay-aS)/this.tickInterval)+1}else{if(ah>100){this.numberTicks=parseInt(3+(ah-100)/75,10)}else{this.numberTicks=2}}}if(this.tickInterval==null){this.tickInterval=av/(this.numberTicks-1)}if(this.max==null){ay=aS+this.tickInterval*(this.numberTicks-1)}if(this.min==null){aS=ay-this.tickInterval*(this.numberTicks-1)}var aF=L.jqplot.getSignificantFigures(this.tickInterval);var aM;if(aF.digitsLeft>=aF.significantDigits){aM="%d"}else{var at=Math.max(0,5-aF.digitsLeft);at=Math.min(at,aF.digitsRight);aM="%."+at+"f"}this._autoFormatString=aM;this.min=aS;this.max=ay}if(this.renderer.constructor==L.jqplot.LinearAxisRenderer&&this._autoFormatString==""){av=this.max-this.min;var a7=new this.tickRenderer(this.tickOptions);var aL=a7.formatString||L.jqplot.config.defaultTickFormatString;var aL=aL.match(L.jqplot.sprintf.regex)[0];var a3=0;if(aL){if(aL.search(/[fFeEgGpP]/)>-1){var aY=aL.match(/\%\.(\d{0,})?[eEfFgGpP]/);if(aY){a3=parseInt(aY[1],10)}else{a3=6}}else{if(aL.search(/[di]/)>-1){a3=0}}var aq=Math.pow(10,-a3);if(this.tickIntervalthis.breakPoints[0]&&aAthis.breakPoints[0]&&aAthis.breakPoints[0]&&aA=this.breakPoints[1]){return(aA-au)*ak/al}else{return(aA+this.breakPoints[1]-this.breakPoints[0]-au)*ak/al}};this.series_p2u=function(aA){return aA*al/ak+au}}}else{this.p2u=function(aA){return(aA-am)*al/ak+at};this.u2p=function(aA){return(aA-at)*ak/al+am};if(this.name=="xaxis"||this.name=="x2axis"){this.series_u2p=function(aA){return(aA-at)*ak/al};this.series_p2u=function(aA){return aA*al/ak+at}}else{this.series_u2p=function(aA){return(aA-au)*ak/al};this.series_p2u=function(aA){return aA*al/ak+au}}}if(this.show){if(this.name=="xaxis"||this.name=="x2axis"){for(var av=0;av0){ah=-ap._textRenderer.height*Math.cos(-ap._textRenderer.angle)/2}else{ah=-ap.getHeight()+ap._textRenderer.height*Math.cos(ap._textRenderer.angle)/2}break;case"middle":ah=-ap.getHeight()/2;break;default:ah=-ap.getHeight()/2;break}}else{ah=-ap.getHeight()/2}var az=this.u2p(ap.value)+ah+"px";ap._elem.css("top",az);ap.pack()}}if(aq){var aw=this._label._elem.outerHeight(true);this._label._elem.css("top",ao-ak/2-aw/2+"px");if(this.name=="yaxis"){this._label._elem.css("left","0px")}else{this._label._elem.css("right","0px")}this._label.pack()}}}ay=null};function i(ai){var ah;ai=Math.abs(ai);if(ai>=10){ah="%d"}else{if(ai>1){if(ai===parseInt(ai,10)){ah="%d"}else{ah="%.1f"}}else{var aj=-Math.floor(Math.log(ai)/Math.LN10);ah="%."+aj+"f"}}return ah}var b=[0.1,0.2,0.3,0.4,0.5,0.8,1,2,3,4,5];var c=function(ai){var ah=b.indexOf(ai);if(ah>0){return b[ah-1]}else{return b[b.length-1]/100}};var k=function(ai){var ah=b.indexOf(ai);if(ah5){ah=10*aj}else{if(am>2){ah=5*aj}else{if(am>1){ah=2*aj}else{ah=aj}}}}else{if(am>5){ah=10*aj}else{if(am>4){ah=5*aj}else{if(am>3){ah=4*aj}else{if(am>2){ah=3*aj}else{if(am>1){ah=2*aj}else{ah=aj}}}}}}return ah}function Q(ai,ah){ah=ah||1;var ak=Math.floor(Math.log(ai)/Math.LN10);var am=Math.pow(10,ak);var al=ai/am;var aj;al=al/ah;if(al<=0.38){aj=0.1}else{if(al<=1.6){aj=0.2}else{if(al<=4){aj=0.5}else{if(al<=8){aj=1}else{if(al<=16){aj=2}else{aj=5}}}}}return aj*am}function x(aj,ai){var al=Math.floor(Math.log(aj)/Math.LN10);var an=Math.pow(10,al);var am=aj/an;var ah;var ak;am=am/ai;if(am<=0.38){ak=0.1}else{if(am<=1.6){ak=0.2}else{if(am<=4){ak=0.5}else{if(am<=8){ak=1}else{if(am<=16){ak=2}else{ak=5}}}}}ah=ak*an;return[ah,ak,an]}L.jqplot.LinearTickGenerator=function(an,aq,aj,ak,ao,ar){ao=(ao===null)?false:ao;ar=(ar===null||ao)?false:ar;if(an===aq){aq=(aq)?0:1}aj=aj||1;if(aqat){at=aB}if(ai>aA){aA=ai}})}an.width=at+Number(av);an.height=aA+Number(ax);var ak=an.getContext("2d");ak.save();ak.fillStyle=al;ak.fillRect(0,0,an.width,an.height);ak.restore();ak.translate(au,ar);ak.textAlign="left";ak.textBaseline="top";function aC(aE){var aF=parseInt(L(aE).css("line-height"),10);if(isNaN(aF)){aF=parseInt(L(aE).css("font-size"),10)*1.2}return aF}function aD(aF,aE,aS,aG,aO,aH){var aQ=aC(aF);var aK=L(aF).innerWidth();var aL=L(aF).innerHeight();var aN=aS.split(/\s+/);var aR=aN.length;var aP="";var aM=[];var aU=aO;var aT=aG;for(var aJ=0;aJaK){aM.push(aJ);aP="";aJ--}}if(aM.length===0){if(L(aF).css("textAlign")==="center"){aT=aG+(aH-aE.measureText(aP).width)/2-au}aE.fillText(aS,aT,aO)}else{aP=aN.slice(0,aM[0]).join(" ");if(L(aF).css("textAlign")==="center"){aT=aG+(aH-aE.measureText(aP).width)/2-au}aE.fillText(aP,aT,aU);aU+=aQ;for(var aJ=1,aI=aM.length;aJ0){ak.strokeRect(aI,aL,L(aG).innerWidth(),L(aG).innerHeight())}L(aG).find("div.jqplot-table-legend-swatch-outline").each(function(){var aU=L(this);ak.strokeStyle=aU.css("border-top-color");var aQ=aI+aU.position().left;var aR=aL+aU.position().top;ak.strokeRect(aQ,aR,aU.innerWidth(),aU.innerHeight());aQ+=parseInt(aU.css("padding-left"),10);aR+=parseInt(aU.css("padding-top"),10);var aT=aU.innerHeight()-2*parseInt(aU.css("padding-top"),10);var aP=aU.innerWidth()-2*parseInt(aU.css("padding-left"),10);var aS=aU.children("div.jqplot-table-legend-swatch");ak.fillStyle=aS.css("background-color");ak.fillRect(aQ,aR,aP,aT)});L(aG).find("td.jqplot-table-legend-label").each(function(){var aR=L(this);var aP=aI+aR.position().left;var aQ=aL+aR.position().top+parseInt(aR.css("padding-top"),10);ak.font=aR.jqplotGetComputedFontStyle();ak.fillStyle=aR.css("color");aD(aR,ak,aR.text(),aP,aQ,aM)});var aH=null}else{if(aN=="canvas"){ak.drawImage(aG,aI,aL)}}}}L(this).children().each(function(){aw(this,av,ax)});return an};L.fn.jqplotToImageStr=function(ai){var ah=L(this).jqplotToImageCanvas(ai);if(ah){return ah.toDataURL("image/png")}else{return null}};L.fn.jqplotToImageElem=function(ah){var ai=document.createElement("img");var aj=L(this).jqplotToImageStr(ah);ai.src=aj;return ai};L.fn.jqplotToImageElemStr=function(ah){var ai="";return ai};L.fn.jqplotSaveImage=function(){var ah=L(this).jqplotToImageStr({});if(ah){window.location.href=ah.replace("image/png","image/octet-stream")}};L.fn.jqplotViewImage=function(){var ai=L(this).jqplotToImageElemStr({});var aj=L(this).jqplotToImageStr({});if(ai){var ah=window.open("");ah.document.open("image/png");ah.document.write(ai);ah.document.close();ah=null}};var ag=function(){this.syntax=ag.config.syntax;this._type="jsDate";this.proxy=new Date();this.options={};this.locale=ag.regional.getLocale();this.formatString="";this.defaultCentury=ag.config.defaultCentury;switch(arguments.length){case 0:break;case 1:if(l(arguments[0])=="[object Object]"&&arguments[0]._type!="jsDate"){var aj=this.options=arguments[0];this.syntax=aj.syntax||this.syntax;this.defaultCentury=aj.defaultCentury||this.defaultCentury;this.proxy=ag.createDate(aj.date)}else{this.proxy=ag.createDate(arguments[0])}break;default:var ah=[];for(var ai=0;ai0?"floor":"ceil"](ak))};ag.prototype.getAbbrDayName=function(){return ag.regional[this.locale]["dayNamesShort"][this.proxy.getDay()]};ag.prototype.getAbbrMonthName=function(){return ag.regional[this.locale]["monthNamesShort"][this.proxy.getMonth()]};ag.prototype.getAMPM=function(){return this.proxy.getHours()>=12?"PM":"AM"};ag.prototype.getAmPm=function(){return this.proxy.getHours()>=12?"pm":"am"};ag.prototype.getCentury=function(){return parseInt(this.proxy.getFullYear()/100,10)};ag.prototype.getDate=function(){return this.proxy.getDate()};ag.prototype.getDay=function(){return this.proxy.getDay()};ag.prototype.getDayOfWeek=function(){var ah=this.proxy.getDay();return ah===0?7:ah};ag.prototype.getDayOfYear=function(){var ai=this.proxy;var ah=ai-new Date(""+ai.getFullYear()+"/1/1 GMT");ah+=ai.getTimezoneOffset()*60000;ai=null;return parseInt(ah/60000/60/24,10)+1};ag.prototype.getDayName=function(){return ag.regional[this.locale]["dayNames"][this.proxy.getDay()]};ag.prototype.getFullWeekOfYear=function(){var ak=this.proxy;var ah=this.getDayOfYear();var aj=6-ak.getDay();var ai=parseInt((ah+aj)/7,10);return ai};ag.prototype.getFullYear=function(){return this.proxy.getFullYear()};ag.prototype.getGmtOffset=function(){var ah=this.proxy.getTimezoneOffset()/60;var ai=ah<0?"+":"-";ah=Math.abs(ah);return ai+N(Math.floor(ah),2)+":"+N((ah%1)*60,2)};ag.prototype.getHours=function(){return this.proxy.getHours()};ag.prototype.getHours12=function(){var ah=this.proxy.getHours();return ah>12?ah-12:(ah==0?12:ah)};ag.prototype.getIsoWeek=function(){var ak=this.proxy;var aj=this.getWeekOfYear();var ah=(new Date(""+ak.getFullYear()+"/1/1")).getDay();var ai=aj+(ah>4||ah<=1?0:1);if(ai==53&&(new Date(""+ak.getFullYear()+"/12/31")).getDay()<4){ai=1}else{if(ai===0){ak=new ag(new Date(""+(ak.getFullYear()-1)+"/12/31"));ai=ak.getIsoWeek()}}ak=null;return ai};ag.prototype.getMilliseconds=function(){return this.proxy.getMilliseconds()};ag.prototype.getMinutes=function(){return this.proxy.getMinutes()};ag.prototype.getMonth=function(){return this.proxy.getMonth()};ag.prototype.getMonthName=function(){return ag.regional[this.locale]["monthNames"][this.proxy.getMonth()]};ag.prototype.getMonthNumber=function(){return this.proxy.getMonth()+1};ag.prototype.getSeconds=function(){return this.proxy.getSeconds()};ag.prototype.getShortYear=function(){return this.proxy.getYear()%100};ag.prototype.getTime=function(){return this.proxy.getTime()};ag.prototype.getTimezoneAbbr=function(){return this.proxy.toString().replace(/^.*\(([^)]+)\)$/,"$1")};ag.prototype.getTimezoneName=function(){var ah=/(?:\((.+)\)$| ([A-Z]{3}) )/.exec(this.toString());return ah[1]||ah[2]||"GMT"+this.getGmtOffset()};ag.prototype.getTimezoneOffset=function(){return this.proxy.getTimezoneOffset()};ag.prototype.getWeekOfYear=function(){var ah=this.getDayOfYear();var aj=7-this.getDayOfWeek();var ai=parseInt((ah+aj)/7,10);return ai};ag.prototype.getUnix=function(){return Math.round(this.proxy.getTime()/1000,0)};ag.prototype.getYear=function(){return this.proxy.getYear()};ag.prototype.next=function(ah){ah=ah||"day";return this.clone().add(1,ah)};ag.prototype.set=function(){switch(arguments.length){case 0:this.proxy=new Date();break;case 1:if(l(arguments[0])=="[object Object]"&&arguments[0]._type!="jsDate"){var aj=this.options=arguments[0];this.syntax=aj.syntax||this.syntax;this.defaultCentury=aj.defaultCentury||this.defaultCentury;this.proxy=ag.createDate(aj.date)}else{this.proxy=ag.createDate(arguments[0])}break;default:var ah=[];for(var ai=0;ai0?"floor":"ceil"](ah/12));var ai=aj.getMonth()+(ah%12);if(ai==12){ai=0;aj.setYear(aj.getFullYear()+1)}else{if(ai==-1){ai=11;aj.setYear(aj.getFullYear()-1)}}aj.setMonth(ai)},diff:function(al,aj){var ah=al.getFullYear()-aj.getFullYear();var ai=al.getMonth()-aj.getMonth()+(ah*12);var ak=al.getDate()-aj.getDate();return ai+(ak/30)}},year:{add:function(ai,ah){ai.setYear(ai.getFullYear()+Math[ah>0?"floor":"ceil"](ah))},diff:function(ai,ah){return E.month.diff(ai,ah)/12}}};for(var Y in E){if(Y.substring(Y.length-1)!="s"){E[Y+"s"]=E[Y]}}var H=function(al,ak,ai){if(ag.formats[ai]["shortcuts"][ak]){return ag.strftime(al,ag.formats[ai]["shortcuts"][ak],ai)}else{var ah=(ag.formats[ai]["codes"][ak]||"").split(".");var aj=al["get"+ah[0]]?al["get"+ah[0]]():"";if(ah[1]){aj=N(aj,ah[1])}return aj}};ag.strftime=function(an,ak,aj,ao){var ai="perl";var am=ag.regional.getLocale();if(aj&&ag.formats.hasOwnProperty(aj)){ai=aj}else{if(aj&&ag.regional.hasOwnProperty(aj)){am=aj}}if(ao&&ag.formats.hasOwnProperty(ao)){ai=ao}else{if(ao&&ag.regional.hasOwnProperty(ao)){am=ao}}if(l(an)!="[object Object]"||an._type!="jsDate"){an=new ag(an);an.locale=am}if(!ak){ak=an.formatString||ag.regional[am]["formatString"]}var ah=ak||"%Y-%m-%d",ap="",al;while(ah.length>0){if(al=ah.match(ag.formats[ai].codes.matcher)){ap+=ah.slice(0,al.index);ap+=(al[1]||"")+H(an,al[2],ai);ah=ah.slice(al.index+al[0].length)}else{ap+=ah;ah=""}}return ap};ag.formats={ISO:"%Y-%m-%dT%H:%M:%S.%N%G",SQL:"%Y-%m-%d %H:%M:%S"};ag.formats.perl={codes:{matcher:/()%(#?(%|[a-z]))/i,Y:"FullYear",y:"ShortYear.2",m:"MonthNumber.2","#m":"MonthNumber",B:"MonthName",b:"AbbrMonthName",d:"Date.2","#d":"Date",e:"Date",A:"DayName",a:"AbbrDayName",w:"Day",H:"Hours.2","#H":"Hours",I:"Hours12.2","#I":"Hours12",p:"AMPM",M:"Minutes.2","#M":"Minutes",S:"Seconds.2","#S":"Seconds",s:"Unix",N:"Milliseconds.3","#N":"Milliseconds",O:"TimezoneOffset",Z:"TimezoneName",G:"GmtOffset"},shortcuts:{F:"%Y-%m-%d",T:"%H:%M:%S",X:"%H:%M:%S",x:"%m/%d/%y",D:"%m/%d/%y","#c":"%a %b %e %H:%M:%S %Y",v:"%e-%b-%Y",R:"%H:%M",r:"%I:%M:%S %p",t:"\t",n:"\n","%":"%"}};ag.formats.php={codes:{matcher:/()%((%|[a-z]))/i,a:"AbbrDayName",A:"DayName",d:"Date.2",e:"Date",j:"DayOfYear.3",u:"DayOfWeek",w:"Day",U:"FullWeekOfYear.2",V:"IsoWeek.2",W:"WeekOfYear.2",b:"AbbrMonthName",B:"MonthName",m:"MonthNumber.2",h:"AbbrMonthName",C:"Century.2",y:"ShortYear.2",Y:"FullYear",H:"Hours.2",I:"Hours12.2",l:"Hours12",p:"AMPM",P:"AmPm",M:"Minutes.2",S:"Seconds.2",s:"Unix",O:"TimezoneOffset",z:"GmtOffset",Z:"TimezoneAbbr"},shortcuts:{D:"%m/%d/%y",F:"%Y-%m-%d",T:"%H:%M:%S",X:"%H:%M:%S",x:"%m/%d/%y",R:"%H:%M",r:"%I:%M:%S %p",t:"\t",n:"\n","%":"%"}};ag.createDate=function(aj){if(aj==null){return new Date()}if(aj instanceof Date){return aj}if(typeof aj=="number"){return new Date(aj)}var ao=String(aj).replace(/^\s*(.+)\s*$/g,"$1");ao=ao.replace(/^([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,4})/,"$1/$2/$3");ao=ao.replace(/^(3[01]|[0-2]?\d)[-\/]([a-z]{3,})[-\/](\d{4})/i,"$1 $2 $3");var an=ao.match(/^(3[01]|[0-2]?\d)[-\/]([a-z]{3,})[-\/](\d{2})\D*/i);if(an&&an.length>3){var at=parseFloat(an[3]);var am=ag.config.defaultCentury+at;am=String(am);ao=ao.replace(/^(3[01]|[0-2]?\d)[-\/]([a-z]{3,})[-\/](\d{2})\D*/i,an[1]+" "+an[2]+" "+am)}an=ao.match(/^([0-9]{1,2})[-\/]([0-9]{1,2})[-\/]([0-9]{1,2})[^0-9]/);function ar(ax,aw){var aC=parseFloat(aw[1]);var aB=parseFloat(aw[2]);var aA=parseFloat(aw[3]);var az=ag.config.defaultCentury;var av,au,aD,ay;if(aC>31){au=aA;aD=aB;av=az+aC}else{au=aB;aD=aC;av=az+aA}ay=aD+"/"+au+"/"+av;return ax.replace(/^([0-9]{1,2})[-\/]([0-9]{1,2})[-\/]([0-9]{1,2})/,ay)}if(an&&an.length>3){ao=ar(ao,an)}var an=ao.match(/^([0-9]{1,2})[-\/]([0-9]{1,2})[-\/]([0-9]{1,2})$/);if(an&&an.length>3){ao=ar(ao,an)}var al=0;var ai=ag.matchers.length;var aq,ah,ap=ao,ak;while(al31){ah=an;ai=am+ao}else{ah=ao;ai=am+an}var ap=ab(aj[2],ag.regional[ag.regional.getLocale()]["monthNamesShort"]);if(ap==-1){ap=ab(aj[2],ag.regional[ag.regional.getLocale()]["monthNames"])}ak.setFullYear(ai,ap,ah);ak.setHours(0,0,0,0);return ak}else{return al}}];function ab(aj,ak){if(ak.indexOf){return ak.indexOf(aj)}for(var ah=0,ai=ak.length;ah=ap)?"":Array(1+ap-au.length>>>0).join(aq);return at?au+ar:ar+au}function ak(ar){var aq=new String(ar);for(var ap=10;ap>0;ap--){if(aq==(aq=aq.replace(/^(\d+)(\d{3})/,"$1"+L.jqplot.sprintf.thousandsSeparator+"$2"))){break}}return aq}function aj(av,au,ax,ar,at,aq){var aw=ar-av.length;if(aw>0){var ap=" ";if(aq){ap=" "}if(ax||!at){av=an(av,ar,ap,ax)}else{av=av.slice(0,au.length)+an("",aw,"0",true)+av.slice(au.length)}}return av}function ao(ay,aq,aw,ar,ap,av,ax,au){var at=ay>>>0;aw=aw&&at&&{"2":"0b","8":"0","16":"0x"}[aq]||"";ay=aw+an(at.toString(aq),av||0,"0",false);return aj(ay,aw,ar,ap,ax,au)}function ah(au,av,ar,ap,at,aq){if(ap!=null){au=au.slice(0,ap)}return aj(au,"",av,ar,at,aq)}var ai=arguments,al=0,am=ai[al++];return am.replace(L.jqplot.sprintf.regex,function(aM,ax,ay,aB,aO,aJ,av){if(aM=="%%"){return"%"}var aD=false,az="",aA=false,aL=false,aw=false,au=false;for(var aI=0;ay&&aI-1?6:(av=="d")?0:void (0)}else{if(aJ=="*"){aJ=+ai[al++]}else{if(aJ.charAt(0)=="*"){aJ=+ai[aJ.slice(1,-1)]}else{aJ=+aJ}}}var aF=ax?ai[ax.slice(0,-1)]:ai[al++];switch(av){case"s":if(aF==null){return""}return ah(String(aF),aD,aB,aJ,aA,aw);case"c":return ah(String.fromCharCode(+aF),aD,aB,aJ,aA,aw);case"b":return ao(aF,2,aL,aD,aB,aJ,aA,aw);case"o":return ao(aF,8,aL,aD,aB,aJ,aA,aw);case"x":return ao(aF,16,aL,aD,aB,aJ,aA,aw);case"X":return ao(aF,16,aL,aD,aB,aJ,aA,aw).toUpperCase();case"u":return ao(aF,10,aL,aD,aB,aJ,aA,aw);case"i":var ar=parseInt(+aF,10);if(isNaN(ar)){return""}var aH=ar<0?"-":az;var aK=au?ak(String(Math.abs(ar))):String(Math.abs(ar));aF=aH+an(aK,aJ,"0",false);return aj(aF,aH,aD,aB,aA,aw);case"d":var ar=Math.round(+aF);if(isNaN(ar)){return""}var aH=ar<0?"-":az;var aK=au?ak(String(Math.abs(ar))):String(Math.abs(ar));aF=aH+an(aK,aJ,"0",false);return aj(aF,aH,aD,aB,aA,aw);case"e":case"E":case"f":case"F":case"g":case"G":var ar=+aF;if(isNaN(ar)){return""}var aH=ar<0?"-":az;var at=["toExponential","toFixed","toPrecision"]["efg".indexOf(av.toLowerCase())];var aN=["toString","toUpperCase"]["eEfFgG".indexOf(av)%2];var aK=Math.abs(ar)[at](aJ);var aE=aK.toString().split(".");aE[0]=au?ak(aE[0]):aE[0];aK=aE.join(L.jqplot.sprintf.decimalMark);aF=aH+aK;var aC=aj(aF,aH,aD,aB,aA,aw)[aN]();return aC;case"p":case"P":var ar=+aF;if(isNaN(ar)){return""}var aH=ar<0?"-":az;var aE=String(Number(Math.abs(ar)).toExponential()).split(/e|E/);var aq=(aE[0].indexOf(".")!=-1)?aE[0].length-1:String(ar).length;var aG=(aE[1]<0)?-aE[1]-1:0;if(Math.abs(ar)<1){if(aq+aG<=aJ){aF=aH+Math.abs(ar).toPrecision(aq)}else{if(aq<=aJ-1){aF=aH+Math.abs(ar).toExponential(aq-1)}else{aF=aH+Math.abs(ar).toExponential(aJ-1)}}}else{var ap=(aq<=aJ)?aq:aJ;aF=aH+Math.abs(ar).toPrecision(ap)}var aN=["toString","toUpperCase"]["pP".indexOf(av)%2];return aj(aF,aH,aD,aB,aA,aw)[aN]();case"n":return"";default:return aM}})};L.jqplot.sprintf.thousandsSeparator=",";L.jqplot.sprintf.decimalMark=".";L.jqplot.sprintf.regex=/%%|%(\d+\$)?([-+#0&\' ]*)(\*\d+\$|\*|\d+)?(\.(\*\d+\$|\*|\d+))?([nAscboxXuidfegpEGP])/g;L.jqplot.getSignificantFigures=function(al){var an=String(Number(Math.abs(al)).toExponential()).split(/e|E/);var am=(an[0].indexOf(".")!=-1)?an[0].length-1:an[0].length;var ai=(an[1]<0)?-an[1]-1:0;var ah=parseInt(an[1],10);var aj=(ah+1>0)?ah+1:0;var ak=(am<=aj)?0:am-ah-1;return{significantDigits:am,digitsLeft:aj,digitsRight:ak,zeros:ai,exponent:ah}};L.jqplot.getPrecision=function(ah){return L.jqplot.getSignificantFigures(ah).digitsRight};var X=L.uiBackCompat!==false;L.jqplot.effects={effect:{}};var m="jqplot.storage.";L.extend(L.jqplot.effects,{version:"1.9pre",save:function(ai,aj){for(var ah=0;ah").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),ah={width:ai.width(),height:ai.height()},ak=document.activeElement;ai.wrap(al);if(ai[0]===ak||L.contains(ai[0],ak)){L(ak).focus()}al=ai.parent();if(ai.css("position")==="static"){al.css({position:"relative"});ai.css({position:"relative"})}else{L.extend(aj,{position:ai.css("position"),zIndex:ai.css("z-index")});L.each(["top","left","bottom","right"],function(am,an){aj[an]=ai.css(an);if(isNaN(parseInt(aj[an],10))){aj[an]="auto"}});ai.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})}ai.css(ah);return al.css(aj).show()},removeWrapper:function(ah){var ai=document.activeElement;if(ah.parent().is(".ui-effects-wrapper")){ah.parent().replaceWith(ah);if(ah[0]===ai||L.contains(ah[0],ai)){L(ai).focus()}}return ah}});function j(ai,ah,aj,ak){if(L.isPlainObject(ai)){return ai}ai={effect:ai};if(ah===u){ah={}}if(L.isFunction(ah)){ak=ah;aj=null;ah={}}if(L.type(ah)==="number"||L.fx.speeds[ah]){ak=aj;aj=ah;ah={}}if(L.isFunction(aj)){ak=aj;aj=null}if(ah){L.extend(ai,ah)}aj=aj||ah.duration;ai.duration=L.fx.off?0:typeof aj==="number"?aj:aj in L.fx.speeds?L.fx.speeds[aj]:L.fx.speeds._default;ai.complete=ak||ah.complete;return ai}function ae(ah){if(!ah||typeof ah==="number"||L.fx.speeds[ah]){return true}if(typeof ah==="string"&&!L.jqplot.effects.effect[ah]){if(X&&L.jqplot.effects[ah]){return false}return true}return false}L.fn.extend({jqplotEffect:function(ap,aq,ai,ao){var an=j.apply(this,arguments),ak=an.mode,al=an.queue,am=L.jqplot.effects.effect[an.effect],ah=!am&&X&&L.jqplot.effects[an.effect];if(L.fx.off||!(am||ah)){if(ak){return this[ak](an.duration,an.complete)}else{return this.each(function(){if(an.complete){an.complete.call(this)}})}}function aj(au){var av=L(this),at=an.complete,aw=an.mode;function ar(){if(L.isFunction(at)){at.call(av[0])}if(L.isFunction(au)){au()}}if(av.is(":hidden")?aw==="hide":aw==="show"){ar()}else{am.call(av[0],an,ar)}}if(am){return al===false?this.each(aj):this.queue(al||"fx",aj)}else{return ah.call(this,{options:an,duration:an.duration,callback:an.complete,mode:an.mode})}}});var a=/up|down|vertical/,v=/up|left|vertical|horizontal/;L.jqplot.effects.effect.blind=function(aj,ao){var ak=L(this),ar=["position","top","bottom","left","right","height","width"],ap=L.jqplot.effects.setMode(ak,aj.mode||"hide"),au=aj.direction||"up",am=a.test(au),al=am?"height":"width",aq=am?"top":"left",aw=v.test(au),an={},av=ap==="show",ai,ah,at;if(ak.parent().is(".ui-effects-wrapper")){L.jqplot.effects.save(ak.parent(),ar)}else{L.jqplot.effects.save(ak,ar)}ak.show();at=parseInt(ak.css("top"),10);ai=L.jqplot.effects.createWrapper(ak).css({overflow:"hidden"});ah=am?ai[al]()+at:ai[al]();an[al]=av?String(ah):"0";if(!aw){ak.css(am?"bottom":"right",0).css(am?"top":"left","").css({position:"absolute"});an[aq]=av?"0":String(ah)}if(av){ai.css(al,0);if(!aw){ai.css(aq,ah)}}ai.animate(an,{duration:aj.duration,easing:aj.easing,queue:false,complete:function(){if(ap==="hide"){ak.hide()}L.jqplot.effects.restore(ak,ar);L.jqplot.effects.removeWrapper(ak);ao()}})}})(jQuery); \ No newline at end of file +(function (L) { + var u; + L.fn.emptyForce = function () { + for (var ah = 0, ai; (ai = L(this)[ah]) != null; ah++) { + if (ai.nodeType === 1) { + L.cleanData(ai.getElementsByTagName("*")); + } + if (L.jqplot.use_excanvas) { + ai.outerHTML = ""; + } else { + while (ai.firstChild) { + ai.removeChild(ai.firstChild); + } + } + ai = null; + } + return L(this); + }; + L.fn.removeChildForce = function (ah) { + while (ah.firstChild) { + this.removeChildForce(ah.firstChild); + ah.removeChild(ah.firstChild); + } + }; + L.fn.jqplot = function () { + var ah = []; + var aj = []; + for (var ak = 0, ai = arguments.length; ak < ai; ak++) { + if (L.isArray(arguments[ak])) { + ah.push(arguments[ak]); + } else { + if (L.isPlainObject(arguments[ak])) { + aj.push(arguments[ak]); + } + } + } + return this.each(function (an) { + var at, + ar, + aq = L(this), + am = ah.length, + al = aj.length, + ap, + ao; + if (an < am) { + ap = ah[an]; + } else { + ap = am ? ah[am - 1] : null; + } + if (an < al) { + ao = aj[an]; + } else { + ao = al ? aj[al - 1] : null; + } + at = aq.attr("id"); + if (at === u) { + at = "jqplot_target_" + L.jqplot.targetCounter++; + aq.attr("id", at); + } + ar = L.jqplot(at, ap, ao); + aq.data("jqplot", ar); + }); + }; + L.jqplot = function (an, ak, ai) { + var aj = null, + ah = null; + if (arguments.length === 3) { + aj = ak; + ah = ai; + } else { + if (arguments.length === 2) { + if (L.isArray(ak)) { + aj = ak; + } else { + if (L.isPlainObject(ak)) { + ah = ak; + } + } + } + } + if (aj === null && ah !== null && ah.data) { + aj = ah.data; + } + var am = new R(); + L("#" + an).removeClass("jqplot-error"); + if (L.jqplot.config.catchErrors) { + try { + am.init(an, aj, ah); + am.draw(); + am.themeEngine.init.call(am); + return am; + } catch (al) { + var ao = L.jqplot.config.errorMessage || al.message; + L("#" + an).append( + '
' + ao + "
", + ); + L("#" + an).addClass("jqplot-error"); + document.getElementById(an).style.background = + L.jqplot.config.errorBackground; + document.getElementById(an).style.border = + L.jqplot.config.errorBorder; + document.getElementById(an).style.fontFamily = + L.jqplot.config.errorFontFamily; + document.getElementById(an).style.fontSize = + L.jqplot.config.errorFontSize; + document.getElementById(an).style.fontStyle = + L.jqplot.config.errorFontStyle; + document.getElementById(an).style.fontWeight = + L.jqplot.config.errorFontWeight; + } + } else { + am.init(an, aj, ah); + am.draw(); + am.themeEngine.init.call(am); + return am; + } + }; + L.jqplot.version = "1.0.8"; + L.jqplot.revision = "1250"; + L.jqplot.targetCounter = 1; + L.jqplot.CanvasManager = function () { + if (typeof L.jqplot.CanvasManager.canvases == "undefined") { + L.jqplot.CanvasManager.canvases = []; + L.jqplot.CanvasManager.free = []; + } + var ah = []; + this.getCanvas = function () { + var ak; + var aj = true; + if (!L.jqplot.use_excanvas) { + for ( + var al = 0, ai = L.jqplot.CanvasManager.canvases.length; + al < ai; + al++ + ) { + if (L.jqplot.CanvasManager.free[al] === true) { + aj = false; + ak = L.jqplot.CanvasManager.canvases[al]; + L.jqplot.CanvasManager.free[al] = false; + ah.push(al); + break; + } + } + } + if (aj) { + ak = document.createElement("canvas"); + ah.push(L.jqplot.CanvasManager.canvases.length); + L.jqplot.CanvasManager.canvases.push(ak); + L.jqplot.CanvasManager.free.push(false); + } + return ak; + }; + this.initCanvas = function (ai) { + if (L.jqplot.use_excanvas) { + return window.G_vmlCanvasManager.initElement(ai); + } + return ai; + }; + this.freeAllCanvases = function () { + for (var aj = 0, ai = ah.length; aj < ai; aj++) { + this.freeCanvas(ah[aj]); + } + ah = []; + }; + this.freeCanvas = function (ai) { + if ( + L.jqplot.use_excanvas && + window.G_vmlCanvasManager.uninitElement !== u + ) { + window.G_vmlCanvasManager.uninitElement( + L.jqplot.CanvasManager.canvases[ai], + ); + L.jqplot.CanvasManager.canvases[ai] = null; + } else { + var aj = L.jqplot.CanvasManager.canvases[ai]; + aj.getContext("2d").clearRect(0, 0, aj.width, aj.height); + L(aj).unbind().removeAttr("class").removeAttr("style"); + L(aj).css({ left: "", top: "", position: "" }); + aj.width = 0; + aj.height = 0; + L.jqplot.CanvasManager.free[ai] = true; + } + }; + }; + L.jqplot.log = function () { + if (window.console) { + window.console.log.apply(window.console, arguments); + } + }; + L.jqplot.config = { + addDomReference: false, + enablePlugins: false, + defaultHeight: 300, + defaultWidth: 400, + UTCAdjust: false, + timezoneOffset: new Date(new Date().getTimezoneOffset() * 60000), + errorMessage: "", + errorBackground: "", + errorBorder: "", + errorFontFamily: "", + errorFontSize: "", + errorFontStyle: "", + errorFontWeight: "", + catchErrors: false, + defaultTickFormatString: "%.1f", + defaultColors: [ + "#4bb2c5", + "#EAA228", + "#c5b47f", + "#579575", + "#839557", + "#958c12", + "#953579", + "#4b5de4", + "#d8b83f", + "#ff5800", + "#0085cc", + "#c747a3", + "#cddf54", + "#FBD178", + "#26B4E3", + "#bd70c7", + ], + defaultNegativeColors: [ + "#498991", + "#C08840", + "#9F9274", + "#546D61", + "#646C4A", + "#6F6621", + "#6E3F5F", + "#4F64B0", + "#A89050", + "#C45923", + "#187399", + "#945381", + "#959E5C", + "#C7AF7B", + "#478396", + "#907294", + ], + dashLength: 4, + gapLength: 4, + dotGapLength: 2.5, + srcLocation: "jqplot/src/", + pluginLocation: "jqplot/src/plugins/", + }; + L.jqplot.arrayMax = function (ah) { + return Math.max.apply(Math, ah); + }; + L.jqplot.arrayMin = function (ah) { + return Math.min.apply(Math, ah); + }; + L.jqplot.enablePlugins = L.jqplot.config.enablePlugins; + L.jqplot.support_canvas = function () { + if (typeof L.jqplot.support_canvas.result == "undefined") { + L.jqplot.support_canvas.result = + !!document.createElement("canvas").getContext; + } + return L.jqplot.support_canvas.result; + }; + L.jqplot.support_canvas_text = function () { + if (typeof L.jqplot.support_canvas_text.result == "undefined") { + if ( + window.G_vmlCanvasManager !== u && + window.G_vmlCanvasManager._version > 887 + ) { + L.jqplot.support_canvas_text.result = true; + } else { + L.jqplot.support_canvas_text.result = !!( + document.createElement("canvas").getContext && + typeof document.createElement("canvas").getContext("2d") + .fillText == "function" + ); + } + } + return L.jqplot.support_canvas_text.result; + }; + L.jqplot.use_excanvas = + (!L.support.boxModel || + !L.support.objectAll || + !$support.leadingWhitespace) && + !L.jqplot.support_canvas() + ? true + : false; + L.jqplot.preInitHooks = []; + L.jqplot.postInitHooks = []; + L.jqplot.preParseOptionsHooks = []; + L.jqplot.postParseOptionsHooks = []; + L.jqplot.preDrawHooks = []; + L.jqplot.postDrawHooks = []; + L.jqplot.preDrawSeriesHooks = []; + L.jqplot.postDrawSeriesHooks = []; + L.jqplot.preDrawLegendHooks = []; + L.jqplot.addLegendRowHooks = []; + L.jqplot.preSeriesInitHooks = []; + L.jqplot.postSeriesInitHooks = []; + L.jqplot.preParseSeriesOptionsHooks = []; + L.jqplot.postParseSeriesOptionsHooks = []; + L.jqplot.eventListenerHooks = []; + L.jqplot.preDrawSeriesShadowHooks = []; + L.jqplot.postDrawSeriesShadowHooks = []; + L.jqplot.ElemContainer = function () { + this._elem; + this._plotWidth; + this._plotHeight; + this._plotDimensions = { height: null, width: null }; + }; + L.jqplot.ElemContainer.prototype.createElement = function ( + ak, + am, + ai, + aj, + an, + ) { + this._offsets = am; + var ah = ai || "jqplot"; + var al = document.createElement(ak); + this._elem = L(al); + this._elem.addClass(ah); + this._elem.css(aj); + this._elem.attr(an); + al = null; + return this._elem; + }; + L.jqplot.ElemContainer.prototype.getWidth = function () { + if (this._elem) { + return this._elem.outerWidth(true); + } else { + return null; + } + }; + L.jqplot.ElemContainer.prototype.getHeight = function () { + if (this._elem) { + return this._elem.outerHeight(true); + } else { + return null; + } + }; + L.jqplot.ElemContainer.prototype.getPosition = function () { + if (this._elem) { + return this._elem.position(); + } else { + return { top: null, left: null, bottom: null, right: null }; + } + }; + L.jqplot.ElemContainer.prototype.getTop = function () { + return this.getPosition().top; + }; + L.jqplot.ElemContainer.prototype.getLeft = function () { + return this.getPosition().left; + }; + L.jqplot.ElemContainer.prototype.getBottom = function () { + return this._elem.css("bottom"); + }; + L.jqplot.ElemContainer.prototype.getRight = function () { + return this._elem.css("right"); + }; + function w(ah) { + L.jqplot.ElemContainer.call(this); + this.name = ah; + this._series = []; + this.show = false; + this.tickRenderer = L.jqplot.AxisTickRenderer; + this.tickOptions = {}; + this.labelRenderer = L.jqplot.AxisLabelRenderer; + this.labelOptions = {}; + this.label = null; + this.showLabel = true; + this.min = null; + this.max = null; + this.autoscale = false; + this.pad = 1.2; + this.padMax = null; + this.padMin = null; + this.ticks = []; + this.numberTicks; + this.tickInterval; + this.renderer = L.jqplot.LinearAxisRenderer; + this.rendererOptions = {}; + this.showTicks = true; + this.showTickMarks = true; + this.showMinorTicks = true; + this.drawMajorGridlines = true; + this.drawMinorGridlines = false; + this.drawMajorTickMarks = true; + this.drawMinorTickMarks = true; + this.useSeriesColor = false; + this.borderWidth = null; + this.borderColor = null; + this.scaleToHiddenSeries = false; + this._dataBounds = { min: null, max: null }; + this._intervalStats = []; + this._offsets = { min: null, max: null }; + this._ticks = []; + this._label = null; + this.syncTicks = null; + this.tickSpacing = 75; + this._min = null; + this._max = null; + this._tickInterval = null; + this._numberTicks = null; + this.__ticks = null; + this._options = {}; + } + w.prototype = new L.jqplot.ElemContainer(); + w.prototype.constructor = w; + w.prototype.init = function () { + if (L.isFunction(this.renderer)) { + this.renderer = new this.renderer(); + } + this.tickOptions.axis = this.name; + if (this.tickOptions.showMark == null) { + this.tickOptions.showMark = this.showTicks; + } + if (this.tickOptions.showMark == null) { + this.tickOptions.showMark = this.showTickMarks; + } + if (this.tickOptions.showLabel == null) { + this.tickOptions.showLabel = this.showTicks; + } + if (this.label == null || this.label == "") { + this.showLabel = false; + } else { + this.labelOptions.label = this.label; + } + if (this.showLabel == false) { + this.labelOptions.show = false; + } + if (this.pad == 0) { + this.pad = 1; + } + if (this.padMax == 0) { + this.padMax = 1; + } + if (this.padMin == 0) { + this.padMin = 1; + } + if (this.padMax == null) { + this.padMax = (this.pad - 1) / 2 + 1; + } + if (this.padMin == null) { + this.padMin = (this.pad - 1) / 2 + 1; + } + this.pad = this.padMax + this.padMin - 1; + if (this.min != null || this.max != null) { + this.autoscale = false; + } + if (this.syncTicks == null && this.name.indexOf("y") > -1) { + this.syncTicks = true; + } else { + if (this.syncTicks == null) { + this.syncTicks = false; + } + } + this.renderer.init.call(this, this.rendererOptions); + }; + w.prototype.draw = function (ah, ai) { + if (this.__ticks) { + this.__ticks = null; + } + return this.renderer.draw.call(this, ah, ai); + }; + w.prototype.set = function () { + this.renderer.set.call(this); + }; + w.prototype.pack = function (ai, ah) { + if (this.show) { + this.renderer.pack.call(this, ai, ah); + } + if (this._min == null) { + this._min = this.min; + this._max = this.max; + this._tickInterval = this.tickInterval; + this._numberTicks = this.numberTicks; + this.__ticks = this._ticks; + } + }; + w.prototype.reset = function () { + this.renderer.reset.call(this); + }; + w.prototype.resetScale = function (ah) { + L.extend( + true, + this, + { + min: null, + max: null, + numberTicks: null, + tickInterval: null, + _ticks: [], + ticks: [], + }, + ah, + ); + this.resetDataBounds(); + }; + w.prototype.resetDataBounds = function () { + var ao = this._dataBounds; + ao.min = null; + ao.max = null; + var ai, ap, am; + var aj = this.show ? true : false; + for (var al = 0; al < this._series.length; al++) { + ap = this._series[al]; + if (ap.show || this.scaleToHiddenSeries) { + am = ap._plotData; + if ( + ap._type === "line" && + ap.renderer.bands.show && + this.name.charAt(0) !== "x" + ) { + am = [ + [0, ap.renderer.bands._min], + [1, ap.renderer.bands._max], + ]; + } + var ah = 1, + an = 1; + if (ap._type != null && ap._type == "ohlc") { + ah = 3; + an = 2; + } + for (var ak = 0, ai = am.length; ak < ai; ak++) { + if (this.name == "xaxis" || this.name == "x2axis") { + if ( + (am[ak][0] != null && am[ak][0] < ao.min) || + ao.min == null + ) { + ao.min = am[ak][0]; + } + if ( + (am[ak][0] != null && am[ak][0] > ao.max) || + ao.max == null + ) { + ao.max = am[ak][0]; + } + } else { + if ( + (am[ak][ah] != null && am[ak][ah] < ao.min) || + ao.min == null + ) { + ao.min = am[ak][ah]; + } + if ( + (am[ak][an] != null && am[ak][an] > ao.max) || + ao.max == null + ) { + ao.max = am[ak][an]; + } + } + } + if (aj && ap.renderer.constructor !== L.jqplot.BarRenderer) { + aj = false; + } else { + if ( + aj && + this._options.hasOwnProperty("forceTickAt0") && + this._options.forceTickAt0 == false + ) { + aj = false; + } else { + if ( + aj && + ap.renderer.constructor === L.jqplot.BarRenderer + ) { + if ( + ap.barDirection == "vertical" && + this.name != "xaxis" && + this.name != "x2axis" + ) { + if ( + this._options.pad != null || + this._options.padMin != null + ) { + aj = false; + } + } else { + if ( + ap.barDirection == "horizontal" && + (this.name == "xaxis" || + this.name == "x2axis") + ) { + if ( + this._options.pad != null || + this._options.padMin != null + ) { + aj = false; + } + } + } + } + } + } + } + } + if ( + aj && + this.renderer.constructor === L.jqplot.LinearAxisRenderer && + ao.min >= 0 + ) { + this.padMin = 1; + this.forceTickAt0 = true; + } + }; + function q(ah) { + L.jqplot.ElemContainer.call(this); + this.show = false; + this.location = "ne"; + this.labels = []; + this.showLabels = true; + this.showSwatches = true; + this.placement = "insideGrid"; + this.xoffset = 0; + this.yoffset = 0; + this.border; + this.background; + this.textColor; + this.fontFamily; + this.fontSize; + this.rowSpacing = "0.5em"; + this.renderer = L.jqplot.TableLegendRenderer; + this.rendererOptions = {}; + this.preDraw = false; + this.marginTop = null; + this.marginRight = null; + this.marginBottom = null; + this.marginLeft = null; + this.escapeHtml = false; + this._series = []; + L.extend(true, this, ah); + } + q.prototype = new L.jqplot.ElemContainer(); + q.prototype.constructor = q; + q.prototype.setOptions = function (ah) { + L.extend(true, this, ah); + if (this.placement == "inside") { + this.placement = "insideGrid"; + } + if (this.xoffset > 0) { + if (this.placement == "insideGrid") { + switch (this.location) { + case "nw": + case "w": + case "sw": + if (this.marginLeft == null) { + this.marginLeft = this.xoffset + "px"; + } + this.marginRight = "0px"; + break; + case "ne": + case "e": + case "se": + default: + if (this.marginRight == null) { + this.marginRight = this.xoffset + "px"; + } + this.marginLeft = "0px"; + break; + } + } else { + if (this.placement == "outside") { + switch (this.location) { + case "nw": + case "w": + case "sw": + if (this.marginRight == null) { + this.marginRight = this.xoffset + "px"; + } + this.marginLeft = "0px"; + break; + case "ne": + case "e": + case "se": + default: + if (this.marginLeft == null) { + this.marginLeft = this.xoffset + "px"; + } + this.marginRight = "0px"; + break; + } + } + } + this.xoffset = 0; + } + if (this.yoffset > 0) { + if (this.placement == "outside") { + switch (this.location) { + case "sw": + case "s": + case "se": + if (this.marginTop == null) { + this.marginTop = this.yoffset + "px"; + } + this.marginBottom = "0px"; + break; + case "ne": + case "n": + case "nw": + default: + if (this.marginBottom == null) { + this.marginBottom = this.yoffset + "px"; + } + this.marginTop = "0px"; + break; + } + } else { + if (this.placement == "insideGrid") { + switch (this.location) { + case "sw": + case "s": + case "se": + if (this.marginBottom == null) { + this.marginBottom = this.yoffset + "px"; + } + this.marginTop = "0px"; + break; + case "ne": + case "n": + case "nw": + default: + if (this.marginTop == null) { + this.marginTop = this.yoffset + "px"; + } + this.marginBottom = "0px"; + break; + } + } + } + this.yoffset = 0; + } + }; + q.prototype.init = function () { + if (L.isFunction(this.renderer)) { + this.renderer = new this.renderer(); + } + this.renderer.init.call(this, this.rendererOptions); + }; + q.prototype.draw = function (ai, aj) { + for (var ah = 0; ah < L.jqplot.preDrawLegendHooks.length; ah++) { + L.jqplot.preDrawLegendHooks[ah].call(this, ai); + } + return this.renderer.draw.call(this, ai, aj); + }; + q.prototype.pack = function (ah) { + this.renderer.pack.call(this, ah); + }; + function y(ah) { + L.jqplot.ElemContainer.call(this); + this.text = ah; + this.show = true; + this.fontFamily; + this.fontSize; + this.textAlign; + this.textColor; + this.renderer = L.jqplot.DivTitleRenderer; + this.rendererOptions = {}; + this.escapeHtml = false; + } + y.prototype = new L.jqplot.ElemContainer(); + y.prototype.constructor = y; + y.prototype.init = function () { + if (L.isFunction(this.renderer)) { + this.renderer = new this.renderer(); + } + this.renderer.init.call(this, this.rendererOptions); + }; + y.prototype.draw = function (ah) { + return this.renderer.draw.call(this, ah); + }; + y.prototype.pack = function () { + this.renderer.pack.call(this); + }; + function S(ah) { + ah = ah || {}; + L.jqplot.ElemContainer.call(this); + this.show = true; + this.xaxis = "xaxis"; + this._xaxis; + this.yaxis = "yaxis"; + this._yaxis; + this.gridBorderWidth = 2; + this.renderer = L.jqplot.LineRenderer; + this.rendererOptions = {}; + this.data = []; + this.gridData = []; + this.label = ""; + this.showLabel = true; + this.color; + this.negativeColor; + this.lineWidth = 2.5; + this.lineJoin = "round"; + this.lineCap = "round"; + this.linePattern = "solid"; + this.shadow = true; + this.shadowAngle = 45; + this.shadowOffset = 1.25; + this.shadowDepth = 3; + this.shadowAlpha = "0.1"; + this.breakOnNull = false; + this.markerRenderer = L.jqplot.MarkerRenderer; + this.markerOptions = {}; + this.showLine = true; + this.showMarker = true; + this.index; + this.fill = false; + this.fillColor; + this.fillAlpha; + this.fillAndStroke = false; + this.disableStack = false; + this._stack = false; + this.neighborThreshold = 4; + this.fillToZero = false; + this.fillToValue = 0; + this.fillAxis = "y"; + this.useNegativeColors = true; + this._stackData = []; + this._plotData = []; + this._plotValues = { x: [], y: [] }; + this._intervals = { x: {}, y: {} }; + this._prevPlotData = []; + this._prevGridData = []; + this._stackAxis = "y"; + this._primaryAxis = "_xaxis"; + this.canvas = new L.jqplot.GenericCanvas(); + this.shadowCanvas = new L.jqplot.GenericCanvas(); + this.plugins = {}; + this._sumy = 0; + this._sumx = 0; + this._type = ""; + } + S.prototype = new L.jqplot.ElemContainer(); + S.prototype.constructor = S; + S.prototype.init = function (ak, ao, am) { + this.index = ak; + this.gridBorderWidth = ao; + var an = this.data; + var aj = [], + al, + ah; + for (al = 0, ah = an.length; al < ah; al++) { + if (!this.breakOnNull) { + if (an[al] == null || an[al][0] == null || an[al][1] == null) { + continue; + } else { + aj.push(an[al]); + } + } else { + aj.push(an[al]); + } + } + this.data = aj; + if (!this.color) { + this.color = am.colorGenerator.get(this.index); + } + if (!this.negativeColor) { + this.negativeColor = am.negativeColorGenerator.get(this.index); + } + if (!this.fillColor) { + this.fillColor = this.color; + } + if (this.fillAlpha) { + var ai = L.jqplot.normalize2rgb(this.fillColor); + var ai = L.jqplot.getColorComponents(ai); + this.fillColor = + "rgba(" + + ai[0] + + "," + + ai[1] + + "," + + ai[2] + + "," + + this.fillAlpha + + ")"; + } + if (L.isFunction(this.renderer)) { + this.renderer = new this.renderer(); + } + this.renderer.init.call(this, this.rendererOptions, am); + this.markerRenderer = new this.markerRenderer(); + if (!this.markerOptions.color) { + this.markerOptions.color = this.color; + } + if (this.markerOptions.show == null) { + this.markerOptions.show = this.showMarker; + } + this.showMarker = this.markerOptions.show; + this.markerRenderer.init(this.markerOptions); + }; + S.prototype.draw = function (an, ak, am) { + var ai = ak == u ? {} : ak; + an = an == u ? this.canvas._ctx : an; + var ah, al, aj; + for (ah = 0; ah < L.jqplot.preDrawSeriesHooks.length; ah++) { + L.jqplot.preDrawSeriesHooks[ah].call(this, an, ai); + } + if (this.show) { + this.renderer.setGridData.call(this, am); + if (!ai.preventJqPlotSeriesDrawTrigger) { + L(an.canvas).trigger("jqplotSeriesDraw", [ + this.data, + this.gridData, + ]); + } + al = []; + if (ai.data) { + al = ai.data; + } else { + if (!this._stack) { + al = this.data; + } else { + al = this._plotData; + } + } + aj = ai.gridData || this.renderer.makeGridData.call(this, al, am); + if ( + this._type === "line" && + this.renderer.smooth && + this.renderer._smoothedData.length + ) { + aj = this.renderer._smoothedData; + } + this.renderer.draw.call(this, an, aj, ai, am); + } + for (ah = 0; ah < L.jqplot.postDrawSeriesHooks.length; ah++) { + L.jqplot.postDrawSeriesHooks[ah].call(this, an, ai, am); + } + an = ak = am = ah = al = aj = null; + }; + S.prototype.drawShadow = function (an, ak, am) { + var ai = ak == u ? {} : ak; + an = an == u ? this.shadowCanvas._ctx : an; + var ah, al, aj; + for (ah = 0; ah < L.jqplot.preDrawSeriesShadowHooks.length; ah++) { + L.jqplot.preDrawSeriesShadowHooks[ah].call(this, an, ai); + } + if (this.shadow) { + this.renderer.setGridData.call(this, am); + al = []; + if (ai.data) { + al = ai.data; + } else { + if (!this._stack) { + al = this.data; + } else { + al = this._plotData; + } + } + aj = ai.gridData || this.renderer.makeGridData.call(this, al, am); + this.renderer.drawShadow.call(this, an, aj, ai, am); + } + for (ah = 0; ah < L.jqplot.postDrawSeriesShadowHooks.length; ah++) { + L.jqplot.postDrawSeriesShadowHooks[ah].call(this, an, ai); + } + an = ak = am = ah = al = aj = null; + }; + S.prototype.toggleDisplay = function (ai, ak) { + var ah, aj; + if (ai.data.series) { + ah = ai.data.series; + } else { + ah = this; + } + if (ai.data.speed) { + aj = ai.data.speed; + } + if (aj) { + if (ah.canvas._elem.is(":hidden") || !ah.show) { + ah.show = true; + ah.canvas._elem.removeClass("jqplot-series-hidden"); + if (ah.shadowCanvas._elem) { + ah.shadowCanvas._elem.fadeIn(aj); + } + ah.canvas._elem.fadeIn(aj, ak); + ah.canvas._elem + .nextAll(".jqplot-point-label.jqplot-series-" + ah.index) + .fadeIn(aj); + } else { + ah.show = false; + ah.canvas._elem.addClass("jqplot-series-hidden"); + if (ah.shadowCanvas._elem) { + ah.shadowCanvas._elem.fadeOut(aj); + } + ah.canvas._elem.fadeOut(aj, ak); + ah.canvas._elem + .nextAll(".jqplot-point-label.jqplot-series-" + ah.index) + .fadeOut(aj); + } + } else { + if (ah.canvas._elem.is(":hidden") || !ah.show) { + ah.show = true; + ah.canvas._elem.removeClass("jqplot-series-hidden"); + if (ah.shadowCanvas._elem) { + ah.shadowCanvas._elem.show(); + } + ah.canvas._elem.show(0, ak); + ah.canvas._elem + .nextAll(".jqplot-point-label.jqplot-series-" + ah.index) + .show(); + } else { + ah.show = false; + ah.canvas._elem.addClass("jqplot-series-hidden"); + if (ah.shadowCanvas._elem) { + ah.shadowCanvas._elem.hide(); + } + ah.canvas._elem.hide(0, ak); + ah.canvas._elem + .nextAll(".jqplot-point-label.jqplot-series-" + ah.index) + .hide(); + } + } + }; + function M() { + L.jqplot.ElemContainer.call(this); + this.drawGridlines = true; + this.gridLineColor = "#cccccc"; + this.gridLineWidth = 1; + this.background = "#fffdf6"; + this.borderColor = "#999999"; + this.borderWidth = 2; + this.drawBorder = true; + this.shadow = true; + this.shadowAngle = 45; + this.shadowOffset = 1.5; + this.shadowWidth = 3; + this.shadowDepth = 3; + this.shadowColor = null; + this.shadowAlpha = "0.07"; + this._left; + this._top; + this._right; + this._bottom; + this._width; + this._height; + this._axes = []; + this.renderer = L.jqplot.CanvasGridRenderer; + this.rendererOptions = {}; + this._offsets = { top: null, bottom: null, left: null, right: null }; + } + M.prototype = new L.jqplot.ElemContainer(); + M.prototype.constructor = M; + M.prototype.init = function () { + if (L.isFunction(this.renderer)) { + this.renderer = new this.renderer(); + } + this.renderer.init.call(this, this.rendererOptions); + }; + M.prototype.createElement = function (ah, ai) { + this._offsets = ah; + return this.renderer.createElement.call(this, ai); + }; + M.prototype.draw = function () { + this.renderer.draw.call(this); + }; + L.jqplot.GenericCanvas = function () { + L.jqplot.ElemContainer.call(this); + this._ctx; + }; + L.jqplot.GenericCanvas.prototype = new L.jqplot.ElemContainer(); + L.jqplot.GenericCanvas.prototype.constructor = L.jqplot.GenericCanvas; + L.jqplot.GenericCanvas.prototype.createElement = function (al, aj, ai, am) { + this._offsets = al; + var ah = "jqplot"; + if (aj != u) { + ah = aj; + } + var ak; + ak = am.canvasManager.getCanvas(); + if (ai != null) { + this._plotDimensions = ai; + } + ak.width = + this._plotDimensions.width - + this._offsets.left - + this._offsets.right; + ak.height = + this._plotDimensions.height - + this._offsets.top - + this._offsets.bottom; + this._elem = L(ak); + this._elem.css({ + position: "absolute", + left: this._offsets.left, + top: this._offsets.top, + }); + this._elem.addClass(ah); + ak = am.canvasManager.initCanvas(ak); + ak = null; + return this._elem; + }; + L.jqplot.GenericCanvas.prototype.setContext = function () { + this._ctx = this._elem.get(0).getContext("2d"); + return this._ctx; + }; + L.jqplot.GenericCanvas.prototype.resetCanvas = function () { + if (this._elem) { + if ( + L.jqplot.use_excanvas && + window.G_vmlCanvasManager.uninitElement !== u + ) { + window.G_vmlCanvasManager.uninitElement(this._elem.get(0)); + } + this._elem.emptyForce(); + } + this._ctx = null; + }; + L.jqplot.HooksManager = function () { + this.hooks = []; + this.args = []; + }; + L.jqplot.HooksManager.prototype.addOnce = function (ak, ai) { + ai = ai || []; + var al = false; + for (var aj = 0, ah = this.hooks.length; aj < ah; aj++) { + if (this.hooks[aj] == ak) { + al = true; + } + } + if (!al) { + this.hooks.push(ak); + this.args.push(ai); + } + }; + L.jqplot.HooksManager.prototype.add = function (ai, ah) { + ah = ah || []; + this.hooks.push(ai); + this.args.push(ah); + }; + L.jqplot.EventListenerManager = function () { + this.hooks = []; + }; + L.jqplot.EventListenerManager.prototype.addOnce = function (al, ak) { + var am = false, + aj, + ai; + for (var ai = 0, ah = this.hooks.length; ai < ah; ai++) { + aj = this.hooks[ai]; + if (aj[0] == al && aj[1] == ak) { + am = true; + } + } + if (!am) { + this.hooks.push([al, ak]); + } + }; + L.jqplot.EventListenerManager.prototype.add = function (ai, ah) { + this.hooks.push([ai, ah]); + }; + var U = [ + "yMidAxis", + "xaxis", + "yaxis", + "x2axis", + "y2axis", + "y3axis", + "y4axis", + "y5axis", + "y6axis", + "y7axis", + "y8axis", + "y9axis", + ]; + function R() { + this.animate = false; + this.animateReplot = false; + this.axes = { + xaxis: new w("xaxis"), + yaxis: new w("yaxis"), + x2axis: new w("x2axis"), + y2axis: new w("y2axis"), + y3axis: new w("y3axis"), + y4axis: new w("y4axis"), + y5axis: new w("y5axis"), + y6axis: new w("y6axis"), + y7axis: new w("y7axis"), + y8axis: new w("y8axis"), + y9axis: new w("y9axis"), + yMidAxis: new w("yMidAxis"), + }; + this.baseCanvas = new L.jqplot.GenericCanvas(); + this.captureRightClick = false; + this.data = []; + this.dataRenderer; + this.dataRendererOptions; + this.defaults = { + axesDefaults: {}, + axes: { + xaxis: {}, + yaxis: {}, + x2axis: {}, + y2axis: {}, + y3axis: {}, + y4axis: {}, + y5axis: {}, + y6axis: {}, + y7axis: {}, + y8axis: {}, + y9axis: {}, + yMidAxis: {}, + }, + seriesDefaults: {}, + series: [], + }; + this.defaultAxisStart = 1; + this.drawIfHidden = false; + this.eventCanvas = new L.jqplot.GenericCanvas(); + this.fillBetween = { + series1: null, + series2: null, + color: null, + baseSeries: 0, + fill: true, + }; + this.fontFamily; + this.fontSize; + this.grid = new M(); + this.legend = new q(); + this.noDataIndicator = { + show: false, + indicator: "Loading Data...", + axes: { + xaxis: { min: 0, max: 10, tickInterval: 2, show: true }, + yaxis: { min: 0, max: 12, tickInterval: 3, show: true }, + }, + }; + this.negativeSeriesColors = L.jqplot.config.defaultNegativeColors; + this.options = {}; + this.previousSeriesStack = []; + this.plugins = {}; + this.series = []; + this.seriesStack = []; + this.seriesColors = L.jqplot.config.defaultColors; + this.sortData = true; + this.stackSeries = false; + this.syncXTicks = true; + this.syncYTicks = true; + this.target = null; + this.targetId = null; + this.textColor; + this.title = new y(); + this._drawCount = 0; + this._sumy = 0; + this._sumx = 0; + this._stackData = []; + this._plotData = []; + this._width = null; + this._height = null; + this._plotDimensions = { height: null, width: null }; + this._gridPadding = { + top: null, + right: null, + bottom: null, + left: null, + }; + this._defaultGridPadding = { top: 10, right: 10, bottom: 23, left: 10 }; + this._addDomReference = L.jqplot.config.addDomReference; + this.preInitHooks = new L.jqplot.HooksManager(); + this.postInitHooks = new L.jqplot.HooksManager(); + this.preParseOptionsHooks = new L.jqplot.HooksManager(); + this.postParseOptionsHooks = new L.jqplot.HooksManager(); + this.preDrawHooks = new L.jqplot.HooksManager(); + this.postDrawHooks = new L.jqplot.HooksManager(); + this.preDrawSeriesHooks = new L.jqplot.HooksManager(); + this.postDrawSeriesHooks = new L.jqplot.HooksManager(); + this.preDrawLegendHooks = new L.jqplot.HooksManager(); + this.addLegendRowHooks = new L.jqplot.HooksManager(); + this.preSeriesInitHooks = new L.jqplot.HooksManager(); + this.postSeriesInitHooks = new L.jqplot.HooksManager(); + this.preParseSeriesOptionsHooks = new L.jqplot.HooksManager(); + this.postParseSeriesOptionsHooks = new L.jqplot.HooksManager(); + this.eventListenerHooks = new L.jqplot.EventListenerManager(); + this.preDrawSeriesShadowHooks = new L.jqplot.HooksManager(); + this.postDrawSeriesShadowHooks = new L.jqplot.HooksManager(); + this.colorGenerator = new L.jqplot.ColorGenerator(); + this.negativeColorGenerator = new L.jqplot.ColorGenerator(); + this.canvasManager = new L.jqplot.CanvasManager(); + this.themeEngine = new L.jqplot.ThemeEngine(); + var aj = 0; + this.init = function (av, ar, ay) { + ay = ay || {}; + for (var at = 0; at < L.jqplot.preInitHooks.length; at++) { + L.jqplot.preInitHooks[at].call(this, av, ar, ay); + } + for (var at = 0; at < this.preInitHooks.hooks.length; at++) { + this.preInitHooks.hooks[at].call(this, av, ar, ay); + } + this.targetId = "#" + av; + this.target = L("#" + av); + if (this._addDomReference) { + this.target.data("jqplot", this); + } + this.target.removeClass("jqplot-error"); + if (!this.target.get(0)) { + throw new Error("No plot target specified"); + } + if (this.target.css("position") == "static") { + this.target.css("position", "relative"); + } + if (!this.target.hasClass("jqplot-target")) { + this.target.addClass("jqplot-target"); + } + if (!this.target.height()) { + var au; + if (ay && ay.height) { + au = parseInt(ay.height, 10); + } else { + if (this.target.attr("data-height")) { + au = parseInt(this.target.attr("data-height"), 10); + } else { + au = parseInt(L.jqplot.config.defaultHeight, 10); + } + } + this._height = au; + this.target.css("height", au + "px"); + } else { + this._height = au = this.target.height(); + } + if (!this.target.width()) { + var aw; + if (ay && ay.width) { + aw = parseInt(ay.width, 10); + } else { + if (this.target.attr("data-width")) { + aw = parseInt(this.target.attr("data-width"), 10); + } else { + aw = parseInt(L.jqplot.config.defaultWidth, 10); + } + } + this._width = aw; + this.target.css("width", aw + "px"); + } else { + this._width = aw = this.target.width(); + } + for (var at = 0, ap = U.length; at < ap; at++) { + this.axes[U[at]] = new w(U[at]); + } + this._plotDimensions.height = this._height; + this._plotDimensions.width = this._width; + this.grid._plotDimensions = this._plotDimensions; + this.title._plotDimensions = this._plotDimensions; + this.baseCanvas._plotDimensions = this._plotDimensions; + this.eventCanvas._plotDimensions = this._plotDimensions; + this.legend._plotDimensions = this._plotDimensions; + if ( + this._height <= 0 || + this._width <= 0 || + !this._height || + !this._width + ) { + throw new Error("Canvas dimension not set"); + } + if (ay.dataRenderer && L.isFunction(ay.dataRenderer)) { + if (ay.dataRendererOptions) { + this.dataRendererOptions = ay.dataRendererOptions; + } + this.dataRenderer = ay.dataRenderer; + ar = this.dataRenderer(ar, this, this.dataRendererOptions); + } + if (ay.noDataIndicator && L.isPlainObject(ay.noDataIndicator)) { + L.extend(true, this.noDataIndicator, ay.noDataIndicator); + } + if ( + ar == null || + L.isArray(ar) == false || + ar.length == 0 || + L.isArray(ar[0]) == false || + ar[0].length == 0 + ) { + if (this.noDataIndicator.show == false) { + throw new Error("No data specified"); + } else { + for (var al in this.noDataIndicator.axes) { + for (var an in this.noDataIndicator.axes[al]) { + this.axes[al][an] = + this.noDataIndicator.axes[al][an]; + } + } + this.postDrawHooks.add(function () { + var aD = this.eventCanvas.getHeight(); + var aA = this.eventCanvas.getWidth(); + var az = L( + '
', + ); + this.target.append(az); + az.height(aD); + az.width(aA); + az.css("top", this.eventCanvas._offsets.top); + az.css("left", this.eventCanvas._offsets.left); + var aC = L( + '
', + ); + az.append(aC); + aC.html(this.noDataIndicator.indicator); + var aB = aC.height(); + var ax = aC.width(); + aC.height(aB); + aC.width(ax); + aC.css("top", (aD - aB) / 2 + "px"); + }); + } + } + this.data = L.extend(true, [], ar); + this.parseOptions(ay); + if (this.textColor) { + this.target.css("color", this.textColor); + } + if (this.fontFamily) { + this.target.css("font-family", this.fontFamily); + } + if (this.fontSize) { + this.target.css("font-size", this.fontSize); + } + this.title.init(); + this.legend.init(); + this._sumy = 0; + this._sumx = 0; + this.computePlotData(); + for (var at = 0; at < this.series.length; at++) { + this.seriesStack.push(at); + this.previousSeriesStack.push(at); + this.series[at].shadowCanvas._plotDimensions = + this._plotDimensions; + this.series[at].canvas._plotDimensions = this._plotDimensions; + for ( + var aq = 0; + aq < L.jqplot.preSeriesInitHooks.length; + aq++ + ) { + L.jqplot.preSeriesInitHooks[aq].call( + this.series[at], + av, + this.data, + this.options.seriesDefaults, + this.options.series[at], + this, + ); + } + for ( + var aq = 0; + aq < this.preSeriesInitHooks.hooks.length; + aq++ + ) { + this.preSeriesInitHooks.hooks[aq].call( + this.series[at], + av, + this.data, + this.options.seriesDefaults, + this.options.series[at], + this, + ); + } + this.series[at]._plotDimensions = this._plotDimensions; + this.series[at].init(at, this.grid.borderWidth, this); + for ( + var aq = 0; + aq < L.jqplot.postSeriesInitHooks.length; + aq++ + ) { + L.jqplot.postSeriesInitHooks[aq].call( + this.series[at], + av, + this.data, + this.options.seriesDefaults, + this.options.series[at], + this, + ); + } + for ( + var aq = 0; + aq < this.postSeriesInitHooks.hooks.length; + aq++ + ) { + this.postSeriesInitHooks.hooks[aq].call( + this.series[at], + av, + this.data, + this.options.seriesDefaults, + this.options.series[at], + this, + ); + } + this._sumy += this.series[at]._sumy; + this._sumx += this.series[at]._sumx; + } + var am, ao; + for (var at = 0, ap = U.length; at < ap; at++) { + am = U[at]; + ao = this.axes[am]; + ao._plotDimensions = this._plotDimensions; + ao.init(); + if (this.axes[am].borderColor == null) { + if ( + am.charAt(0) !== "x" && + ao.useSeriesColor === true && + ao.show + ) { + ao.borderColor = ao._series[0].color; + } else { + ao.borderColor = this.grid.borderColor; + } + } + } + if (this.sortData) { + ah(this.series); + } + this.grid.init(); + this.grid._axes = this.axes; + this.legend._series = this.series; + for (var at = 0; at < L.jqplot.postInitHooks.length; at++) { + L.jqplot.postInitHooks[at].call(this, av, this.data, ay); + } + for (var at = 0; at < this.postInitHooks.hooks.length; at++) { + this.postInitHooks.hooks[at].call(this, av, this.data, ay); + } + }; + this.resetAxesScale = function (aq, am) { + var ao = am || {}; + var ap = aq || this.axes; + if (ap === true) { + ap = this.axes; + } + if (L.isArray(ap)) { + for (var an = 0; an < ap.length; an++) { + this.axes[ap[an]].resetScale(ao[ap[an]]); + } + } else { + if (typeof ap === "object") { + for (var al in ap) { + this.axes[al].resetScale(ao[al]); + } + } + } + }; + this.reInitialize = function (au, al) { + var ay = L.extend(true, {}, this.options, al); + var aw = this.targetId.substr(1); + var ar = au == null ? this.data : au; + for (var av = 0; av < L.jqplot.preInitHooks.length; av++) { + L.jqplot.preInitHooks[av].call(this, aw, ar, ay); + } + for (var av = 0; av < this.preInitHooks.hooks.length; av++) { + this.preInitHooks.hooks[av].call(this, aw, ar, ay); + } + this._height = this.target.height(); + this._width = this.target.width(); + if ( + this._height <= 0 || + this._width <= 0 || + !this._height || + !this._width + ) { + throw new Error("Target dimension not set"); + } + this._plotDimensions.height = this._height; + this._plotDimensions.width = this._width; + this.grid._plotDimensions = this._plotDimensions; + this.title._plotDimensions = this._plotDimensions; + this.baseCanvas._plotDimensions = this._plotDimensions; + this.eventCanvas._plotDimensions = this._plotDimensions; + this.legend._plotDimensions = this._plotDimensions; + var am, ax, at, ao; + for (var av = 0, aq = U.length; av < aq; av++) { + am = U[av]; + ao = this.axes[am]; + ax = ao._ticks; + for (var at = 0, ap = ax.length; at < ap; at++) { + var an = ax[at]._elem; + if (an) { + if ( + L.jqplot.use_excanvas && + window.G_vmlCanvasManager.uninitElement !== u + ) { + window.G_vmlCanvasManager.uninitElement(an.get(0)); + } + an.emptyForce(); + an = null; + ax._elem = null; + } + } + ax = null; + delete ao.ticks; + delete ao._ticks; + this.axes[am] = new w(am); + this.axes[am]._plotWidth = this._width; + this.axes[am]._plotHeight = this._height; + } + if (au) { + if (ay.dataRenderer && L.isFunction(ay.dataRenderer)) { + if (ay.dataRendererOptions) { + this.dataRendererOptions = ay.dataRendererOptions; + } + this.dataRenderer = ay.dataRenderer; + au = this.dataRenderer(au, this, this.dataRendererOptions); + } + this.data = L.extend(true, [], au); + } + if (al) { + this.parseOptions(ay); + } + this.title._plotWidth = this._width; + if (this.textColor) { + this.target.css("color", this.textColor); + } + if (this.fontFamily) { + this.target.css("font-family", this.fontFamily); + } + if (this.fontSize) { + this.target.css("font-size", this.fontSize); + } + this.title.init(); + this.legend.init(); + this._sumy = 0; + this._sumx = 0; + this.seriesStack = []; + this.previousSeriesStack = []; + this.computePlotData(); + for (var av = 0, aq = this.series.length; av < aq; av++) { + this.seriesStack.push(av); + this.previousSeriesStack.push(av); + this.series[av].shadowCanvas._plotDimensions = + this._plotDimensions; + this.series[av].canvas._plotDimensions = this._plotDimensions; + for ( + var at = 0; + at < L.jqplot.preSeriesInitHooks.length; + at++ + ) { + L.jqplot.preSeriesInitHooks[at].call( + this.series[av], + aw, + this.data, + this.options.seriesDefaults, + this.options.series[av], + this, + ); + } + for ( + var at = 0; + at < this.preSeriesInitHooks.hooks.length; + at++ + ) { + this.preSeriesInitHooks.hooks[at].call( + this.series[av], + aw, + this.data, + this.options.seriesDefaults, + this.options.series[av], + this, + ); + } + this.series[av]._plotDimensions = this._plotDimensions; + this.series[av].init(av, this.grid.borderWidth, this); + for ( + var at = 0; + at < L.jqplot.postSeriesInitHooks.length; + at++ + ) { + L.jqplot.postSeriesInitHooks[at].call( + this.series[av], + aw, + this.data, + this.options.seriesDefaults, + this.options.series[av], + this, + ); + } + for ( + var at = 0; + at < this.postSeriesInitHooks.hooks.length; + at++ + ) { + this.postSeriesInitHooks.hooks[at].call( + this.series[av], + aw, + this.data, + this.options.seriesDefaults, + this.options.series[av], + this, + ); + } + this._sumy += this.series[av]._sumy; + this._sumx += this.series[av]._sumx; + } + for (var av = 0, aq = U.length; av < aq; av++) { + am = U[av]; + ao = this.axes[am]; + ao._plotDimensions = this._plotDimensions; + ao.init(); + if (ao.borderColor == null) { + if ( + am.charAt(0) !== "x" && + ao.useSeriesColor === true && + ao.show + ) { + ao.borderColor = ao._series[0].color; + } else { + ao.borderColor = this.grid.borderColor; + } + } + } + if (this.sortData) { + ah(this.series); + } + this.grid.init(); + this.grid._axes = this.axes; + this.legend._series = this.series; + for ( + var av = 0, aq = L.jqplot.postInitHooks.length; + av < aq; + av++ + ) { + L.jqplot.postInitHooks[av].call(this, aw, this.data, ay); + } + for ( + var av = 0, aq = this.postInitHooks.hooks.length; + av < aq; + av++ + ) { + this.postInitHooks.hooks[av].call(this, aw, this.data, ay); + } + }; + this.quickInit = function () { + this._height = this.target.height(); + this._width = this.target.width(); + if ( + this._height <= 0 || + this._width <= 0 || + !this._height || + !this._width + ) { + throw new Error("Target dimension not set"); + } + this._plotDimensions.height = this._height; + this._plotDimensions.width = this._width; + this.grid._plotDimensions = this._plotDimensions; + this.title._plotDimensions = this._plotDimensions; + this.baseCanvas._plotDimensions = this._plotDimensions; + this.eventCanvas._plotDimensions = this._plotDimensions; + this.legend._plotDimensions = this._plotDimensions; + for (var aq in this.axes) { + this.axes[aq]._plotWidth = this._width; + this.axes[aq]._plotHeight = this._height; + } + this.title._plotWidth = this._width; + if (this.textColor) { + this.target.css("color", this.textColor); + } + if (this.fontFamily) { + this.target.css("font-family", this.fontFamily); + } + if (this.fontSize) { + this.target.css("font-size", this.fontSize); + } + this._sumy = 0; + this._sumx = 0; + this.computePlotData(); + for (var ao = 0; ao < this.series.length; ao++) { + if ( + this.series[ao]._type === "line" && + this.series[ao].renderer.bands.show + ) { + this.series[ao].renderer.initBands.call( + this.series[ao], + this.series[ao].renderer.options, + this, + ); + } + this.series[ao]._plotDimensions = this._plotDimensions; + this.series[ao].canvas._plotDimensions = this._plotDimensions; + this._sumy += this.series[ao]._sumy; + this._sumx += this.series[ao]._sumx; + } + var am; + for (var al = 0; al < 12; al++) { + am = U[al]; + var an = this.axes[am]._ticks; + for (var ao = 0; ao < an.length; ao++) { + var ap = an[ao]._elem; + if (ap) { + if ( + L.jqplot.use_excanvas && + window.G_vmlCanvasManager.uninitElement !== u + ) { + window.G_vmlCanvasManager.uninitElement(ap.get(0)); + } + ap.emptyForce(); + ap = null; + an._elem = null; + } + } + an = null; + this.axes[am]._plotDimensions = this._plotDimensions; + this.axes[am]._ticks = []; + } + if (this.sortData) { + ah(this.series); + } + this.grid._axes = this.axes; + this.legend._series = this.series; + }; + function ah(ap) { + var au, av, aw, al, at; + for (var aq = 0; aq < ap.length; aq++) { + var am; + var ar = [ + ap[aq].data, + ap[aq]._stackData, + ap[aq]._plotData, + ap[aq]._prevPlotData, + ]; + for (var an = 0; an < 4; an++) { + am = true; + au = ar[an]; + if (ap[aq]._stackAxis == "x") { + for (var ao = 0; ao < au.length; ao++) { + if (typeof au[ao][1] != "number") { + am = false; + break; + } + } + if (am) { + au.sort(function (ay, ax) { + return ay[1] - ax[1]; + }); + } + } else { + for (var ao = 0; ao < au.length; ao++) { + if (typeof au[ao][0] != "number") { + am = false; + break; + } + } + if (am) { + au.sort(function (ay, ax) { + return ay[0] - ax[0]; + }); + } + } + } + } + } + this.computePlotData = function () { + this._plotData = []; + this._stackData = []; + var at, au, ao; + for (au = 0, ao = this.series.length; au < ao; au++) { + at = this.series[au]; + this._plotData.push([]); + this._stackData.push([]); + var am = at.data; + this._plotData[au] = L.extend(true, [], am); + this._stackData[au] = L.extend(true, [], am); + at._plotData = this._plotData[au]; + at._stackData = this._stackData[au]; + var ax = { x: [], y: [] }; + if (this.stackSeries && !at.disableStack) { + at._stack = true; + var av = at._stackAxis === "x" ? 0 : 1; + for (var ap = 0, al = am.length; ap < al; ap++) { + var aw = am[ap][av]; + if (aw == null) { + aw = 0; + } + this._plotData[au][ap][av] = aw; + this._stackData[au][ap][av] = aw; + if (au > 0) { + for (var aq = au; aq--; ) { + var an = this._plotData[aq][ap][av]; + if (aw * an >= 0) { + this._plotData[au][ap][av] += an; + this._stackData[au][ap][av] += an; + break; + } + } + } + } + } else { + for (var ar = 0; ar < at.data.length; ar++) { + ax.x.push(at.data[ar][0]); + ax.y.push(at.data[ar][1]); + } + this._stackData.push(at.data); + this.series[au]._stackData = at.data; + this._plotData.push(at.data); + at._plotData = at.data; + at._plotValues = ax; + } + if (au > 0) { + at._prevPlotData = this.series[au - 1]._plotData; + } + at._sumy = 0; + at._sumx = 0; + for (ar = at.data.length - 1; ar > -1; ar--) { + at._sumy += at.data[ar][1]; + at._sumx += at.data[ar][0]; + } + } + }; + this.populatePlotData = function (au, av) { + this._plotData = []; + this._stackData = []; + au._stackData = []; + au._plotData = []; + var ay = { x: [], y: [] }; + if (this.stackSeries && !au.disableStack) { + au._stack = true; + var ax = au._stackAxis === "x" ? 0 : 1; + var az = L.extend(true, [], au.data); + var aA = L.extend(true, [], au.data); + var an, am, ao, aw, al; + for (var ar = 0; ar < av; ar++) { + var ap = this.series[ar].data; + for (var aq = 0; aq < ap.length; aq++) { + ao = ap[aq]; + an = ao[0] != null ? ao[0] : 0; + am = ao[1] != null ? ao[1] : 0; + az[aq][0] += an; + az[aq][1] += am; + aw = ax ? am : an; + if (au.data[aq][ax] * aw >= 0) { + aA[aq][ax] += aw; + } + } + } + for (var at = 0; at < aA.length; at++) { + ay.x.push(aA[at][0]); + ay.y.push(aA[at][1]); + } + this._plotData.push(aA); + this._stackData.push(az); + au._stackData = az; + au._plotData = aA; + au._plotValues = ay; + } else { + for (var at = 0; at < au.data.length; at++) { + ay.x.push(au.data[at][0]); + ay.y.push(au.data[at][1]); + } + this._stackData.push(au.data); + this.series[av]._stackData = au.data; + this._plotData.push(au.data); + au._plotData = au.data; + au._plotValues = ay; + } + if (av > 0) { + au._prevPlotData = this.series[av - 1]._plotData; + } + au._sumy = 0; + au._sumx = 0; + for (at = au.data.length - 1; at > -1; at--) { + au._sumy += au.data[at][1]; + au._sumx += au.data[at][0]; + } + }; + this.getNextSeriesColor = (function (am) { + var al = 0; + var an = am.seriesColors; + return function () { + if (al < an.length) { + return an[al++]; + } else { + al = 0; + return an[al++]; + } + }; + })(this); + this.parseOptions = function (ay) { + for ( + var at = 0; + at < this.preParseOptionsHooks.hooks.length; + at++ + ) { + this.preParseOptionsHooks.hooks[at].call(this, ay); + } + for (var at = 0; at < L.jqplot.preParseOptionsHooks.length; at++) { + L.jqplot.preParseOptionsHooks[at].call(this, ay); + } + this.options = L.extend(true, {}, this.defaults, ay); + var am = this.options; + this.animate = am.animate; + this.animateReplot = am.animateReplot; + this.stackSeries = am.stackSeries; + if (L.isPlainObject(am.fillBetween)) { + var ax = ["series1", "series2", "color", "baseSeries", "fill"], + au; + for (var at = 0, aq = ax.length; at < aq; at++) { + au = ax[at]; + if (am.fillBetween[au] != null) { + this.fillBetween[au] = am.fillBetween[au]; + } + } + } + if (am.seriesColors) { + this.seriesColors = am.seriesColors; + } + if (am.negativeSeriesColors) { + this.negativeSeriesColors = am.negativeSeriesColors; + } + if (am.captureRightClick) { + this.captureRightClick = am.captureRightClick; + } + this.defaultAxisStart = + ay && ay.defaultAxisStart != null + ? ay.defaultAxisStart + : this.defaultAxisStart; + this.colorGenerator.setColors(this.seriesColors); + this.negativeColorGenerator.setColors(this.negativeSeriesColors); + L.extend(true, this._gridPadding, am.gridPadding); + this.sortData = am.sortData != null ? am.sortData : this.sortData; + for (var at = 0; at < 12; at++) { + var an = U[at]; + var ap = this.axes[an]; + ap._options = L.extend(true, {}, am.axesDefaults, am.axes[an]); + L.extend(true, ap, am.axesDefaults, am.axes[an]); + ap._plotWidth = this._width; + ap._plotHeight = this._height; + } + var aw = function (aD, aB, aE) { + var aA = []; + var aC, az; + aB = aB || "vertical"; + if (!L.isArray(aD[0])) { + for (aC = 0, az = aD.length; aC < az; aC++) { + if (aB == "vertical") { + aA.push([aE + aC, aD[aC]]); + } else { + aA.push([aD[aC], aE + aC]); + } + } + } else { + L.extend(true, aA, aD); + } + return aA; + }; + var av = 0; + this.series = []; + for (var at = 0; at < this.data.length; at++) { + var al = L.extend( + true, + { index: at }, + { + seriesColors: this.seriesColors, + negativeSeriesColors: this.negativeSeriesColors, + }, + this.options.seriesDefaults, + this.options.series[at], + { rendererOptions: { animation: { show: this.animate } } }, + ); + var ax = new S(al); + for ( + var ar = 0; + ar < L.jqplot.preParseSeriesOptionsHooks.length; + ar++ + ) { + L.jqplot.preParseSeriesOptionsHooks[ar].call( + ax, + this.options.seriesDefaults, + this.options.series[at], + ); + } + for ( + var ar = 0; + ar < this.preParseSeriesOptionsHooks.hooks.length; + ar++ + ) { + this.preParseSeriesOptionsHooks.hooks[ar].call( + ax, + this.options.seriesDefaults, + this.options.series[at], + ); + } + L.extend(true, ax, al); + var ao = "vertical"; + if ( + ax.renderer === L.jqplot.BarRenderer && + ax.rendererOptions && + ax.rendererOptions.barDirection == "horizontal" + ) { + ao = "horizontal"; + ax._stackAxis = "x"; + ax._primaryAxis = "_yaxis"; + } + ax.data = aw(this.data[at], ao, this.defaultAxisStart); + switch (ax.xaxis) { + case "xaxis": + ax._xaxis = this.axes.xaxis; + break; + case "x2axis": + ax._xaxis = this.axes.x2axis; + break; + default: + break; + } + ax._yaxis = this.axes[ax.yaxis]; + ax._xaxis._series.push(ax); + ax._yaxis._series.push(ax); + if (ax.show) { + ax._xaxis.show = true; + ax._yaxis.show = true; + } else { + if (ax._xaxis.scaleToHiddenSeries) { + ax._xaxis.show = true; + } + if (ax._yaxis.scaleToHiddenSeries) { + ax._yaxis.show = true; + } + } + if (!ax.label) { + ax.label = "Series " + (at + 1).toString(); + } + this.series.push(ax); + for ( + var ar = 0; + ar < L.jqplot.postParseSeriesOptionsHooks.length; + ar++ + ) { + L.jqplot.postParseSeriesOptionsHooks[ar].call( + this.series[at], + this.options.seriesDefaults, + this.options.series[at], + ); + } + for ( + var ar = 0; + ar < this.postParseSeriesOptionsHooks.hooks.length; + ar++ + ) { + this.postParseSeriesOptionsHooks.hooks[ar].call( + this.series[at], + this.options.seriesDefaults, + this.options.series[at], + ); + } + } + L.extend(true, this.grid, this.options.grid); + for (var at = 0, aq = U.length; at < aq; at++) { + var an = U[at]; + var ap = this.axes[an]; + if (ap.borderWidth == null) { + ap.borderWidth = this.grid.borderWidth; + } + } + if (typeof this.options.title == "string") { + this.title.text = this.options.title; + } else { + if (typeof this.options.title == "object") { + L.extend(true, this.title, this.options.title); + } + } + this.title._plotWidth = this._width; + this.legend.setOptions(this.options.legend); + for (var at = 0; at < L.jqplot.postParseOptionsHooks.length; at++) { + L.jqplot.postParseOptionsHooks[at].call(this, ay); + } + for ( + var at = 0; + at < this.postParseOptionsHooks.hooks.length; + at++ + ) { + this.postParseOptionsHooks.hooks[at].call(this, ay); + } + }; + this.destroy = function () { + this.canvasManager.freeAllCanvases(); + if (this.eventCanvas && this.eventCanvas._elem) { + this.eventCanvas._elem.unbind(); + } + this.target.empty(); + this.target[0].innerHTML = ""; + }; + this.replot = function (am) { + var an = am || {}; + var ap = an.data || null; + var al = an.clear === false ? false : true; + var ao = an.resetAxes || false; + delete an.data; + delete an.clear; + delete an.resetAxes; + this.target.trigger("jqplotPreReplot"); + if (al) { + this.destroy(); + } + if (ap || !L.isEmptyObject(an)) { + this.reInitialize(ap, an); + } else { + this.quickInit(); + } + if (ao) { + this.resetAxesScale(ao, an.axes); + } + this.draw(); + this.target.trigger("jqplotPostReplot"); + }; + this.redraw = function (al) { + al = al != null ? al : true; + this.target.trigger("jqplotPreRedraw"); + if (al) { + this.canvasManager.freeAllCanvases(); + this.eventCanvas._elem.unbind(); + this.target.empty(); + } + for (var an in this.axes) { + this.axes[an]._ticks = []; + } + this.computePlotData(); + this._sumy = 0; + this._sumx = 0; + for (var am = 0, ao = this.series.length; am < ao; am++) { + this._sumy += this.series[am]._sumy; + this._sumx += this.series[am]._sumx; + } + this.draw(); + this.target.trigger("jqplotPostRedraw"); + }; + this.draw = function () { + if (this.drawIfHidden || this.target.is(":visible")) { + this.target.trigger("jqplotPreDraw"); + var aH, aF, aE, ao; + for (aH = 0, aE = L.jqplot.preDrawHooks.length; aH < aE; aH++) { + L.jqplot.preDrawHooks[aH].call(this); + } + for ( + aH = 0, aE = this.preDrawHooks.hooks.length; + aH < aE; + aH++ + ) { + this.preDrawHooks.hooks[aH].apply( + this, + this.preDrawSeriesHooks.args[aH], + ); + } + this.target.append( + this.baseCanvas.createElement( + { left: 0, right: 0, top: 0, bottom: 0 }, + "jqplot-base-canvas", + null, + this, + ), + ); + this.baseCanvas.setContext(); + this.target.append(this.title.draw()); + this.title.pack({ top: 0, left: 0 }); + var aL = this.legend.draw({}, this); + var al = { top: 0, left: 0, bottom: 0, right: 0 }; + if (this.legend.placement == "outsideGrid") { + this.target.append(aL); + switch (this.legend.location) { + case "n": + al.top += this.legend.getHeight(); + break; + case "s": + al.bottom += this.legend.getHeight(); + break; + case "ne": + case "e": + case "se": + al.right += this.legend.getWidth(); + break; + case "nw": + case "w": + case "sw": + al.left += this.legend.getWidth(); + break; + default: + al.right += this.legend.getWidth(); + break; + } + aL = aL.detach(); + } + var ar = this.axes; + var aM; + for (aH = 0; aH < 12; aH++) { + aM = U[aH]; + this.target.append(ar[aM].draw(this.baseCanvas._ctx, this)); + ar[aM].set(); + } + if (ar.yaxis.show) { + al.left += ar.yaxis.getWidth(); + } + var aG = [ + "y2axis", + "y3axis", + "y4axis", + "y5axis", + "y6axis", + "y7axis", + "y8axis", + "y9axis", + ]; + var az = [0, 0, 0, 0, 0, 0, 0, 0]; + var aC = 0; + var aB; + for (aB = 0; aB < 8; aB++) { + if (ar[aG[aB]].show) { + aC += ar[aG[aB]].getWidth(); + az[aB] = aC; + } + } + al.right += aC; + if (ar.x2axis.show) { + al.top += ar.x2axis.getHeight(); + } + if (this.title.show) { + al.top += this.title.getHeight(); + } + if (ar.xaxis.show) { + al.bottom += ar.xaxis.getHeight(); + } + if ( + this.options.gridDimensions && + L.isPlainObject(this.options.gridDimensions) + ) { + var at = + parseInt(this.options.gridDimensions.width, 10) || 0; + var aI = + parseInt(this.options.gridDimensions.height, 10) || 0; + var an = (this._width - al.left - al.right - at) / 2; + var aK = (this._height - al.top - al.bottom - aI) / 2; + if (aK >= 0 && an >= 0) { + al.top += aK; + al.bottom += aK; + al.left += an; + al.right += an; + } + } + var am = ["top", "bottom", "left", "right"]; + for (var aB in am) { + if (this._gridPadding[am[aB]] == null && al[am[aB]] > 0) { + this._gridPadding[am[aB]] = al[am[aB]]; + } else { + if (this._gridPadding[am[aB]] == null) { + this._gridPadding[am[aB]] = + this._defaultGridPadding[am[aB]]; + } + } + } + var aA = this._gridPadding; + if (this.legend.placement === "outsideGrid") { + aA = { + top: this.title.getHeight(), + left: 0, + right: 0, + bottom: 0, + }; + if (this.legend.location === "s") { + aA.left = this._gridPadding.left; + aA.right = this._gridPadding.right; + } + } + ar.xaxis.pack( + { + position: "absolute", + bottom: this._gridPadding.bottom - ar.xaxis.getHeight(), + left: 0, + width: this._width, + }, + { + min: this._gridPadding.left, + max: this._width - this._gridPadding.right, + }, + ); + ar.yaxis.pack( + { + position: "absolute", + top: 0, + left: this._gridPadding.left - ar.yaxis.getWidth(), + height: this._height, + }, + { + min: this._height - this._gridPadding.bottom, + max: this._gridPadding.top, + }, + ); + ar.x2axis.pack( + { + position: "absolute", + top: this._gridPadding.top - ar.x2axis.getHeight(), + left: 0, + width: this._width, + }, + { + min: this._gridPadding.left, + max: this._width - this._gridPadding.right, + }, + ); + for (aH = 8; aH > 0; aH--) { + ar[aG[aH - 1]].pack( + { + position: "absolute", + top: 0, + right: this._gridPadding.right - az[aH - 1], + }, + { + min: this._height - this._gridPadding.bottom, + max: this._gridPadding.top, + }, + ); + } + var au = + (this._width - + this._gridPadding.left - + this._gridPadding.right) / + 2 + + this._gridPadding.left - + ar.yMidAxis.getWidth() / 2; + ar.yMidAxis.pack( + { + position: "absolute", + top: 0, + left: au, + zIndex: 9, + textAlign: "center", + }, + { + min: this._height - this._gridPadding.bottom, + max: this._gridPadding.top, + }, + ); + this.target.append( + this.grid.createElement(this._gridPadding, this), + ); + this.grid.draw(); + var aq = this.series; + var aJ = aq.length; + for (aH = 0, aE = aJ; aH < aE; aH++) { + aF = this.seriesStack[aH]; + this.target.append( + aq[aF].shadowCanvas.createElement( + this._gridPadding, + "jqplot-series-shadowCanvas", + null, + this, + ), + ); + aq[aF].shadowCanvas.setContext(); + aq[aF].shadowCanvas._elem.data("seriesIndex", aF); + } + for (aH = 0, aE = aJ; aH < aE; aH++) { + aF = this.seriesStack[aH]; + this.target.append( + aq[aF].canvas.createElement( + this._gridPadding, + "jqplot-series-canvas", + null, + this, + ), + ); + aq[aF].canvas.setContext(); + aq[aF].canvas._elem.data("seriesIndex", aF); + } + this.target.append( + this.eventCanvas.createElement( + this._gridPadding, + "jqplot-event-canvas", + null, + this, + ), + ); + this.eventCanvas.setContext(); + this.eventCanvas._ctx.fillStyle = "rgba(0,0,0,0)"; + this.eventCanvas._ctx.fillRect( + 0, + 0, + this.eventCanvas._ctx.canvas.width, + this.eventCanvas._ctx.canvas.height, + ); + this.bindCustomEvents(); + if (this.legend.preDraw) { + this.eventCanvas._elem.before(aL); + this.legend.pack(aA); + if (this.legend._elem) { + this.drawSeries({ + legendInfo: { + location: this.legend.location, + placement: this.legend.placement, + width: this.legend.getWidth(), + height: this.legend.getHeight(), + xoffset: this.legend.xoffset, + yoffset: this.legend.yoffset, + }, + }); + } else { + this.drawSeries(); + } + } else { + this.drawSeries(); + if (aJ) { + L(aq[aJ - 1].canvas._elem).after(aL); + } + this.legend.pack(aA); + } + for ( + var aH = 0, aE = L.jqplot.eventListenerHooks.length; + aH < aE; + aH++ + ) { + this.eventCanvas._elem.bind( + L.jqplot.eventListenerHooks[aH][0], + { plot: this }, + L.jqplot.eventListenerHooks[aH][1], + ); + } + for ( + var aH = 0, aE = this.eventListenerHooks.hooks.length; + aH < aE; + aH++ + ) { + this.eventCanvas._elem.bind( + this.eventListenerHooks.hooks[aH][0], + { plot: this }, + this.eventListenerHooks.hooks[aH][1], + ); + } + var ay = this.fillBetween; + if ( + ay.fill && + ay.series1 !== ay.series2 && + ay.series1 < aJ && + ay.series2 < aJ && + aq[ay.series1]._type === "line" && + aq[ay.series2]._type === "line" + ) { + this.doFillBetweenLines(); + } + for ( + var aH = 0, aE = L.jqplot.postDrawHooks.length; + aH < aE; + aH++ + ) { + L.jqplot.postDrawHooks[aH].call(this); + } + for ( + var aH = 0, aE = this.postDrawHooks.hooks.length; + aH < aE; + aH++ + ) { + this.postDrawHooks.hooks[aH].apply( + this, + this.postDrawHooks.args[aH], + ); + } + if (this.target.is(":visible")) { + this._drawCount += 1; + } + var av, aw, aD, ap; + for (aH = 0, aE = aJ; aH < aE; aH++) { + av = aq[aH]; + aw = av.renderer; + aD = ".jqplot-point-label.jqplot-series-" + aH; + if ( + aw.animation && + aw.animation._supported && + aw.animation.show && + (this._drawCount < 2 || this.animateReplot) + ) { + ap = this.target.find(aD); + ap.stop(true, true).hide(); + av.canvas._elem.stop(true, true).hide(); + av.shadowCanvas._elem.stop(true, true).hide(); + av.canvas._elem.jqplotEffect( + "blind", + { mode: "show", direction: aw.animation.direction }, + aw.animation.speed, + ); + av.shadowCanvas._elem.jqplotEffect( + "blind", + { mode: "show", direction: aw.animation.direction }, + aw.animation.speed, + ); + ap.fadeIn(aw.animation.speed * 0.8); + } + } + ap = null; + this.target.trigger("jqplotPostDraw", [this]); + } + }; + R.prototype.doFillBetweenLines = function () { + var an = this.fillBetween; + var ax = an.series1; + var av = an.series2; + var aw = ax < av ? ax : av; + var au = av > ax ? av : ax; + var ar = this.series[aw]; + var aq = this.series[au]; + if (aq.renderer.smooth) { + var ap = aq.renderer._smoothedData.slice(0).reverse(); + } else { + var ap = aq.gridData.slice(0).reverse(); + } + if (ar.renderer.smooth) { + var at = ar.renderer._smoothedData.concat(ap); + } else { + var at = ar.gridData.concat(ap); + } + var ao = an.color !== null ? an.color : this.series[ax].fillColor; + var ay = an.baseSeries !== null ? an.baseSeries : aw; + var am = this.series[ay].renderer.shapeRenderer; + var al = { fillStyle: ao, fill: true, closePath: true }; + am.draw(ar.shadowCanvas._ctx, at, al); + }; + this.bindCustomEvents = function () { + this.eventCanvas._elem.bind("click", { plot: this }, this.onClick); + this.eventCanvas._elem.bind( + "dblclick", + { plot: this }, + this.onDblClick, + ); + this.eventCanvas._elem.bind( + "mousedown", + { plot: this }, + this.onMouseDown, + ); + this.eventCanvas._elem.bind( + "mousemove", + { plot: this }, + this.onMouseMove, + ); + this.eventCanvas._elem.bind( + "mouseenter", + { plot: this }, + this.onMouseEnter, + ); + this.eventCanvas._elem.bind( + "mouseleave", + { plot: this }, + this.onMouseLeave, + ); + if (this.captureRightClick) { + this.eventCanvas._elem.bind( + "mouseup", + { plot: this }, + this.onRightClick, + ); + this.eventCanvas._elem.get(0).oncontextmenu = function () { + return false; + }; + } else { + this.eventCanvas._elem.bind( + "mouseup", + { plot: this }, + this.onMouseUp, + ); + } + }; + function ai(av) { + var au = av.data.plot; + var ap = au.eventCanvas._elem.offset(); + var at = { x: av.pageX - ap.left, y: av.pageY - ap.top }; + var aq = { + xaxis: null, + yaxis: null, + x2axis: null, + y2axis: null, + y3axis: null, + y4axis: null, + y5axis: null, + y6axis: null, + y7axis: null, + y8axis: null, + y9axis: null, + yMidAxis: null, + }; + var ar = [ + "xaxis", + "yaxis", + "x2axis", + "y2axis", + "y3axis", + "y4axis", + "y5axis", + "y6axis", + "y7axis", + "y8axis", + "y9axis", + "yMidAxis", + ]; + var al = au.axes; + var am, ao; + for (am = 11; am > 0; am--) { + ao = ar[am - 1]; + if (al[ao].show) { + aq[ao] = al[ao].series_p2u(at[ao.charAt(0)]); + } + } + return { offsets: ap, gridPos: at, dataPos: aq }; + } + function ak(al, am) { + var aq = am.series; + var aW, aU, aT, aO, aP, aJ, aI, aw, au, az, aA, aK; + var aS, aX, aQ, ar, aH, aM, aV; + var an, aN; + for (aT = am.seriesStack.length - 1; aT >= 0; aT--) { + aW = am.seriesStack[aT]; + aO = aq[aW]; + aV = aO._highlightThreshold; + switch (aO.renderer.constructor) { + case L.jqplot.BarRenderer: + aJ = al.x; + aI = al.y; + for (aU = 0; aU < aO._barPoints.length; aU++) { + aH = aO._barPoints[aU]; + aQ = aO.gridData[aU]; + if ( + aJ > aH[0][0] && + aJ < aH[2][0] && + aI > aH[2][1] && + aI < aH[0][1] + ) { + return { + seriesIndex: aO.index, + pointIndex: aU, + gridData: aQ, + data: aO.data[aU], + points: aO._barPoints[aU], + }; + } + } + break; + case L.jqplot.PyramidRenderer: + aJ = al.x; + aI = al.y; + for (aU = 0; aU < aO._barPoints.length; aU++) { + aH = aO._barPoints[aU]; + aQ = aO.gridData[aU]; + if ( + aJ > aH[0][0] + aV[0][0] && + aJ < aH[2][0] + aV[2][0] && + aI > aH[2][1] && + aI < aH[0][1] + ) { + return { + seriesIndex: aO.index, + pointIndex: aU, + gridData: aQ, + data: aO.data[aU], + points: aO._barPoints[aU], + }; + } + } + break; + case L.jqplot.DonutRenderer: + az = (aO.startAngle / 180) * Math.PI; + aJ = al.x - aO._center[0]; + aI = al.y - aO._center[1]; + aP = Math.sqrt(Math.pow(aJ, 2) + Math.pow(aI, 2)); + if (aJ > 0 && -aI >= 0) { + aw = 2 * Math.PI - Math.atan(-aI / aJ); + } else { + if (aJ > 0 && -aI < 0) { + aw = -Math.atan(-aI / aJ); + } else { + if (aJ < 0) { + aw = Math.PI - Math.atan(-aI / aJ); + } else { + if (aJ == 0 && -aI > 0) { + aw = (3 * Math.PI) / 2; + } else { + if (aJ == 0 && -aI < 0) { + aw = Math.PI / 2; + } else { + if (aJ == 0 && aI == 0) { + aw = 0; + } + } + } + } + } + } + if (az) { + aw -= az; + if (aw < 0) { + aw += 2 * Math.PI; + } else { + if (aw > 2 * Math.PI) { + aw -= 2 * Math.PI; + } + } + } + au = (aO.sliceMargin / 180) * Math.PI; + if (aP < aO._radius && aP > aO._innerRadius) { + for (aU = 0; aU < aO.gridData.length; aU++) { + aA = aU > 0 ? aO.gridData[aU - 1][1] + au : au; + aK = aO.gridData[aU][1]; + if (aw > aA && aw < aK) { + return { + seriesIndex: aO.index, + pointIndex: aU, + gridData: [al.x, al.y], + data: aO.data[aU], + }; + } + } + } + break; + case L.jqplot.PieRenderer: + az = (aO.startAngle / 180) * Math.PI; + aJ = al.x - aO._center[0]; + aI = al.y - aO._center[1]; + aP = Math.sqrt(Math.pow(aJ, 2) + Math.pow(aI, 2)); + if (aJ > 0 && -aI >= 0) { + aw = 2 * Math.PI - Math.atan(-aI / aJ); + } else { + if (aJ > 0 && -aI < 0) { + aw = -Math.atan(-aI / aJ); + } else { + if (aJ < 0) { + aw = Math.PI - Math.atan(-aI / aJ); + } else { + if (aJ == 0 && -aI > 0) { + aw = (3 * Math.PI) / 2; + } else { + if (aJ == 0 && -aI < 0) { + aw = Math.PI / 2; + } else { + if (aJ == 0 && aI == 0) { + aw = 0; + } + } + } + } + } + } + if (az) { + aw -= az; + if (aw < 0) { + aw += 2 * Math.PI; + } else { + if (aw > 2 * Math.PI) { + aw -= 2 * Math.PI; + } + } + } + au = (aO.sliceMargin / 180) * Math.PI; + if (aP < aO._radius) { + for (aU = 0; aU < aO.gridData.length; aU++) { + aA = aU > 0 ? aO.gridData[aU - 1][1] + au : au; + aK = aO.gridData[aU][1]; + if (aw > aA && aw < aK) { + return { + seriesIndex: aO.index, + pointIndex: aU, + gridData: [al.x, al.y], + data: aO.data[aU], + }; + } + } + } + break; + case L.jqplot.BubbleRenderer: + aJ = al.x; + aI = al.y; + var aF = null; + if (aO.show) { + for (var aU = 0; aU < aO.gridData.length; aU++) { + aQ = aO.gridData[aU]; + aX = Math.sqrt( + (aJ - aQ[0]) * (aJ - aQ[0]) + + (aI - aQ[1]) * (aI - aQ[1]), + ); + if (aX <= aQ[2] && (aX <= aS || aS == null)) { + aS = aX; + aF = { + seriesIndex: aW, + pointIndex: aU, + gridData: aQ, + data: aO.data[aU], + }; + } + } + if (aF != null) { + return aF; + } + } + break; + case L.jqplot.FunnelRenderer: + aJ = al.x; + aI = al.y; + var aL = aO._vertices, + ap = aL[0], + ao = aL[aL.length - 1], + at, + aE, + ay; + function aR(a0, a2, a1) { + var aZ = (a2[1] - a1[1]) / (a2[0] - a1[0]); + var aY = a2[1] - aZ * a2[0]; + var a3 = a0 + a2[1]; + return [(a3 - aY) / aZ, a3]; + } + at = aR(aI, ap[0], ao[3]); + aE = aR(aI, ap[1], ao[2]); + for (aU = 0; aU < aL.length; aU++) { + ay = aL[aU]; + if ( + aI >= ay[0][1] && + aI <= ay[3][1] && + aJ >= at[0] && + aJ <= aE[0] + ) { + return { + seriesIndex: aO.index, + pointIndex: aU, + gridData: null, + data: aO.data[aU], + }; + } + } + break; + case L.jqplot.LineRenderer: + aJ = al.x; + aI = al.y; + aP = aO.renderer; + if (aO.show) { + if ( + (aO.fill || + (aO.renderer.bands.show && + aO.renderer.bands.fill)) && + (!am.plugins.highlighter || + !am.plugins.highlighter.show) + ) { + var ax = false; + if ( + aJ > aO._boundingBox[0][0] && + aJ < aO._boundingBox[1][0] && + aI > aO._boundingBox[1][1] && + aI < aO._boundingBox[0][1] + ) { + var aD = aO._areaPoints.length; + var aG; + var aU = aD - 1; + for (var aG = 0; aG < aD; aG++) { + var aC = [ + aO._areaPoints[aG][0], + aO._areaPoints[aG][1], + ]; + var aB = [ + aO._areaPoints[aU][0], + aO._areaPoints[aU][1], + ]; + if ( + (aC[1] < aI && aB[1] >= aI) || + (aB[1] < aI && aC[1] >= aI) + ) { + if ( + aC[0] + + ((aI - aC[1]) / + (aB[1] - aC[1])) * + (aB[0] - aC[0]) < + aJ + ) { + ax = !ax; + } + } + aU = aG; + } + } + if (ax) { + return { + seriesIndex: aW, + pointIndex: null, + gridData: aO.gridData, + data: aO.data, + points: aO._areaPoints, + }; + } + break; + } else { + aN = + aO.markerRenderer.size / 2 + + aO.neighborThreshold; + an = aN > 0 ? aN : 0; + for ( + var aU = 0; + aU < aO.gridData.length; + aU++ + ) { + aQ = aO.gridData[aU]; + if ( + aP.constructor == L.jqplot.OHLCRenderer + ) { + if (aP.candleStick) { + var av = aO._yaxis.series_u2p; + if ( + aJ >= + aQ[0] - aP._bodyWidth / 2 && + aJ <= + aQ[0] + aP._bodyWidth / 2 && + aI >= av(aO.data[aU][2]) && + aI <= av(aO.data[aU][3]) + ) { + return { + seriesIndex: aW, + pointIndex: aU, + gridData: aQ, + data: aO.data[aU], + }; + } + } else { + if (!aP.hlc) { + var av = aO._yaxis.series_u2p; + if ( + aJ >= + aQ[0] - + aP._tickLength && + aJ <= + aQ[0] + + aP._tickLength && + aI >= av(aO.data[aU][2]) && + aI <= av(aO.data[aU][3]) + ) { + return { + seriesIndex: aW, + pointIndex: aU, + gridData: aQ, + data: aO.data[aU], + }; + } + } else { + var av = aO._yaxis.series_u2p; + if ( + aJ >= + aQ[0] - + aP._tickLength && + aJ <= + aQ[0] + + aP._tickLength && + aI >= av(aO.data[aU][1]) && + aI <= av(aO.data[aU][2]) + ) { + return { + seriesIndex: aW, + pointIndex: aU, + gridData: aQ, + data: aO.data[aU], + }; + } + } + } + } else { + if (aQ[0] != null && aQ[1] != null) { + aX = Math.sqrt( + (aJ - aQ[0]) * (aJ - aQ[0]) + + (aI - aQ[1]) * (aI - aQ[1]), + ); + if ( + aX <= an && + (aX <= aS || aS == null) + ) { + aS = aX; + return { + seriesIndex: aW, + pointIndex: aU, + gridData: aQ, + data: aO.data[aU], + }; + } + } + } + } + } + } + break; + default: + aJ = al.x; + aI = al.y; + aP = aO.renderer; + if (aO.show) { + aN = + aO.markerRenderer.size / 2 + + aO.neighborThreshold; + an = aN > 0 ? aN : 0; + for (var aU = 0; aU < aO.gridData.length; aU++) { + aQ = aO.gridData[aU]; + if (aP.constructor == L.jqplot.OHLCRenderer) { + if (aP.candleStick) { + var av = aO._yaxis.series_u2p; + if ( + aJ >= aQ[0] - aP._bodyWidth / 2 && + aJ <= aQ[0] + aP._bodyWidth / 2 && + aI >= av(aO.data[aU][2]) && + aI <= av(aO.data[aU][3]) + ) { + return { + seriesIndex: aW, + pointIndex: aU, + gridData: aQ, + data: aO.data[aU], + }; + } + } else { + if (!aP.hlc) { + var av = aO._yaxis.series_u2p; + if ( + aJ >= aQ[0] - aP._tickLength && + aJ <= aQ[0] + aP._tickLength && + aI >= av(aO.data[aU][2]) && + aI <= av(aO.data[aU][3]) + ) { + return { + seriesIndex: aW, + pointIndex: aU, + gridData: aQ, + data: aO.data[aU], + }; + } + } else { + var av = aO._yaxis.series_u2p; + if ( + aJ >= aQ[0] - aP._tickLength && + aJ <= aQ[0] + aP._tickLength && + aI >= av(aO.data[aU][1]) && + aI <= av(aO.data[aU][2]) + ) { + return { + seriesIndex: aW, + pointIndex: aU, + gridData: aQ, + data: aO.data[aU], + }; + } + } + } + } else { + aX = Math.sqrt( + (aJ - aQ[0]) * (aJ - aQ[0]) + + (aI - aQ[1]) * (aI - aQ[1]), + ); + if (aX <= an && (aX <= aS || aS == null)) { + aS = aX; + return { + seriesIndex: aW, + pointIndex: aU, + gridData: aQ, + data: aO.data[aU], + }; + } + } + } + } + break; + } + } + return null; + } + this.onClick = function (an) { + var am = ai(an); + var ap = an.data.plot; + var ao = ak(am.gridPos, ap); + var al = L.Event("jqplotClick"); + al.pageX = an.pageX; + al.pageY = an.pageY; + L(this).trigger(al, [am.gridPos, am.dataPos, ao, ap]); + }; + this.onDblClick = function (an) { + var am = ai(an); + var ap = an.data.plot; + var ao = ak(am.gridPos, ap); + var al = L.Event("jqplotDblClick"); + al.pageX = an.pageX; + al.pageY = an.pageY; + L(this).trigger(al, [am.gridPos, am.dataPos, ao, ap]); + }; + this.onMouseDown = function (an) { + var am = ai(an); + var ap = an.data.plot; + var ao = ak(am.gridPos, ap); + var al = L.Event("jqplotMouseDown"); + al.pageX = an.pageX; + al.pageY = an.pageY; + L(this).trigger(al, [am.gridPos, am.dataPos, ao, ap]); + }; + this.onMouseUp = function (an) { + var am = ai(an); + var al = L.Event("jqplotMouseUp"); + al.pageX = an.pageX; + al.pageY = an.pageY; + L(this).trigger(al, [am.gridPos, am.dataPos, null, an.data.plot]); + }; + this.onRightClick = function (an) { + var am = ai(an); + var ap = an.data.plot; + var ao = ak(am.gridPos, ap); + if (ap.captureRightClick) { + if (an.which == 3) { + var al = L.Event("jqplotRightClick"); + al.pageX = an.pageX; + al.pageY = an.pageY; + L(this).trigger(al, [am.gridPos, am.dataPos, ao, ap]); + } else { + var al = L.Event("jqplotMouseUp"); + al.pageX = an.pageX; + al.pageY = an.pageY; + L(this).trigger(al, [am.gridPos, am.dataPos, ao, ap]); + } + } + }; + this.onMouseMove = function (an) { + var am = ai(an); + var ap = an.data.plot; + var ao = ak(am.gridPos, ap); + var al = L.Event("jqplotMouseMove"); + al.pageX = an.pageX; + al.pageY = an.pageY; + L(this).trigger(al, [am.gridPos, am.dataPos, ao, ap]); + }; + this.onMouseEnter = function (an) { + var am = ai(an); + var ao = an.data.plot; + var al = L.Event("jqplotMouseEnter"); + al.pageX = an.pageX; + al.pageY = an.pageY; + al.relatedTarget = an.relatedTarget; + L(this).trigger(al, [am.gridPos, am.dataPos, null, ao]); + }; + this.onMouseLeave = function (an) { + var am = ai(an); + var ao = an.data.plot; + var al = L.Event("jqplotMouseLeave"); + al.pageX = an.pageX; + al.pageY = an.pageY; + al.relatedTarget = an.relatedTarget; + L(this).trigger(al, [am.gridPos, am.dataPos, null, ao]); + }; + this.drawSeries = function (an, al) { + var ap, ao, am; + al = typeof an === "number" && al == null ? an : al; + an = typeof an === "object" ? an : {}; + if (al != u) { + ao = this.series[al]; + am = ao.shadowCanvas._ctx; + am.clearRect(0, 0, am.canvas.width, am.canvas.height); + ao.drawShadow(am, an, this); + am = ao.canvas._ctx; + am.clearRect(0, 0, am.canvas.width, am.canvas.height); + ao.draw(am, an, this); + if (ao.renderer.constructor == L.jqplot.BezierCurveRenderer) { + if (al < this.series.length - 1) { + this.drawSeries(al + 1); + } + } + } else { + for (ap = 0; ap < this.series.length; ap++) { + ao = this.series[ap]; + am = ao.shadowCanvas._ctx; + am.clearRect(0, 0, am.canvas.width, am.canvas.height); + ao.drawShadow(am, an, this); + am = ao.canvas._ctx; + am.clearRect(0, 0, am.canvas.width, am.canvas.height); + ao.draw(am, an, this); + } + } + an = al = ap = ao = am = null; + }; + this.moveSeriesToFront = function (am) { + am = parseInt(am, 10); + var ap = L.inArray(am, this.seriesStack); + if (ap == -1) { + return; + } + if (ap == this.seriesStack.length - 1) { + this.previousSeriesStack = this.seriesStack.slice(0); + return; + } + var al = this.seriesStack[this.seriesStack.length - 1]; + var ao = this.series[am].canvas._elem.detach(); + var an = this.series[am].shadowCanvas._elem.detach(); + this.series[al].shadowCanvas._elem.after(an); + this.series[al].canvas._elem.after(ao); + this.previousSeriesStack = this.seriesStack.slice(0); + this.seriesStack.splice(ap, 1); + this.seriesStack.push(am); + }; + this.moveSeriesToBack = function (am) { + am = parseInt(am, 10); + var ap = L.inArray(am, this.seriesStack); + if (ap == 0 || ap == -1) { + return; + } + var al = this.seriesStack[0]; + var ao = this.series[am].canvas._elem.detach(); + var an = this.series[am].shadowCanvas._elem.detach(); + this.series[al].shadowCanvas._elem.before(an); + this.series[al].canvas._elem.before(ao); + this.previousSeriesStack = this.seriesStack.slice(0); + this.seriesStack.splice(ap, 1); + this.seriesStack.unshift(am); + }; + this.restorePreviousSeriesOrder = function () { + var ar, aq, ap, ao, an, al, am; + if (this.seriesStack == this.previousSeriesStack) { + return; + } + for (ar = 1; ar < this.previousSeriesStack.length; ar++) { + al = this.previousSeriesStack[ar]; + am = this.previousSeriesStack[ar - 1]; + ap = this.series[al].canvas._elem.detach(); + ao = this.series[al].shadowCanvas._elem.detach(); + this.series[am].shadowCanvas._elem.after(ao); + this.series[am].canvas._elem.after(ap); + } + an = this.seriesStack.slice(0); + this.seriesStack = this.previousSeriesStack.slice(0); + this.previousSeriesStack = an; + }; + this.restoreOriginalSeriesOrder = function () { + var ap, + ao, + al = [], + an, + am; + for (ap = 0; ap < this.series.length; ap++) { + al.push(ap); + } + if (this.seriesStack == al) { + return; + } + this.previousSeriesStack = this.seriesStack.slice(0); + this.seriesStack = al; + for (ap = 1; ap < this.seriesStack.length; ap++) { + an = this.series[ap].canvas._elem.detach(); + am = this.series[ap].shadowCanvas._elem.detach(); + this.series[ap - 1].shadowCanvas._elem.after(am); + this.series[ap - 1].canvas._elem.after(an); + } + }; + this.activateTheme = function (al) { + this.themeEngine.activate(this, al); + }; + } + L.jqplot.computeHighlightColors = function (ai) { + var ak; + if (L.isArray(ai)) { + ak = []; + for (var am = 0; am < ai.length; am++) { + var al = L.jqplot.getColorComponents(ai[am]); + var ah = [al[0], al[1], al[2]]; + var an = ah[0] + ah[1] + ah[2]; + for (var aj = 0; aj < 3; aj++) { + ah[aj] = an > 660 ? ah[aj] * 0.85 : 0.73 * ah[aj] + 90; + ah[aj] = parseInt(ah[aj], 10); + ah[aj] > 255 ? 255 : ah[aj]; + } + ah[3] = 0.3 + 0.35 * al[3]; + ak.push( + "rgba(" + + ah[0] + + "," + + ah[1] + + "," + + ah[2] + + "," + + ah[3] + + ")", + ); + } + } else { + var al = L.jqplot.getColorComponents(ai); + var ah = [al[0], al[1], al[2]]; + var an = ah[0] + ah[1] + ah[2]; + for (var aj = 0; aj < 3; aj++) { + ah[aj] = an > 660 ? ah[aj] * 0.85 : 0.73 * ah[aj] + 90; + ah[aj] = parseInt(ah[aj], 10); + ah[aj] > 255 ? 255 : ah[aj]; + } + ah[3] = 0.3 + 0.35 * al[3]; + ak = + "rgba(" + ah[0] + "," + ah[1] + "," + ah[2] + "," + ah[3] + ")"; + } + return ak; + }; + L.jqplot.ColorGenerator = function (ai) { + ai = ai || L.jqplot.config.defaultColors; + var ah = 0; + this.next = function () { + if (ah < ai.length) { + return ai[ah++]; + } else { + ah = 0; + return ai[ah++]; + } + }; + this.previous = function () { + if (ah > 0) { + return ai[ah--]; + } else { + ah = ai.length - 1; + return ai[ah]; + } + }; + this.get = function (ak) { + var aj = ak - ai.length * Math.floor(ak / ai.length); + return ai[aj]; + }; + this.setColors = function (aj) { + ai = aj; + }; + this.reset = function () { + ah = 0; + }; + this.getIndex = function () { + return ah; + }; + this.setIndex = function (aj) { + ah = aj; + }; + }; + L.jqplot.hex2rgb = function (aj, ah) { + aj = aj.replace("#", ""); + if (aj.length == 3) { + aj = + aj.charAt(0) + + aj.charAt(0) + + aj.charAt(1) + + aj.charAt(1) + + aj.charAt(2) + + aj.charAt(2); + } + var ai; + ai = + "rgba(" + + parseInt(aj.slice(0, 2), 16) + + ", " + + parseInt(aj.slice(2, 4), 16) + + ", " + + parseInt(aj.slice(4, 6), 16); + if (ah) { + ai += ", " + ah; + } + ai += ")"; + return ai; + }; + L.jqplot.rgb2hex = function (am) { + var aj = + /rgba?\( *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *(?:, *[0-9.]*)?\)/; + var ah = am.match(aj); + var al = "#"; + for (var ak = 1; ak < 4; ak++) { + var ai; + if (ah[ak].search(/%/) != -1) { + ai = parseInt((255 * ah[ak]) / 100, 10).toString(16); + if (ai.length == 1) { + ai = "0" + ai; + } + } else { + ai = parseInt(ah[ak], 10).toString(16); + if (ai.length == 1) { + ai = "0" + ai; + } + } + al += ai; + } + return al; + }; + L.jqplot.normalize2rgb = function (ai, ah) { + if (ai.search(/^ *rgba?\(/) != -1) { + return ai; + } else { + if (ai.search(/^ *#?[0-9a-fA-F]?[0-9a-fA-F]/) != -1) { + return L.jqplot.hex2rgb(ai, ah); + } else { + throw new Error("Invalid color spec"); + } + } + }; + L.jqplot.getColorComponents = function (am) { + am = L.jqplot.colorKeywordMap[am] || am; + var ak = L.jqplot.normalize2rgb(am); + var aj = + /rgba?\( *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *,? *([0-9.]* *)?\)/; + var ah = ak.match(aj); + var ai = []; + for (var al = 1; al < 4; al++) { + if (ah[al].search(/%/) != -1) { + ai[al - 1] = parseInt((255 * ah[al]) / 100, 10); + } else { + ai[al - 1] = parseInt(ah[al], 10); + } + } + ai[3] = parseFloat(ah[4]) ? parseFloat(ah[4]) : 1; + return ai; + }; + L.jqplot.colorKeywordMap = { + aliceblue: "rgb(240, 248, 255)", + antiquewhite: "rgb(250, 235, 215)", + aqua: "rgb( 0, 255, 255)", + aquamarine: "rgb(127, 255, 212)", + azure: "rgb(240, 255, 255)", + beige: "rgb(245, 245, 220)", + bisque: "rgb(255, 228, 196)", + black: "rgb( 0, 0, 0)", + blanchedalmond: "rgb(255, 235, 205)", + blue: "rgb( 0, 0, 255)", + blueviolet: "rgb(138, 43, 226)", + brown: "rgb(165, 42, 42)", + burlywood: "rgb(222, 184, 135)", + cadetblue: "rgb( 95, 158, 160)", + chartreuse: "rgb(127, 255, 0)", + chocolate: "rgb(210, 105, 30)", + coral: "rgb(255, 127, 80)", + cornflowerblue: "rgb(100, 149, 237)", + cornsilk: "rgb(255, 248, 220)", + crimson: "rgb(220, 20, 60)", + cyan: "rgb( 0, 255, 255)", + darkblue: "rgb( 0, 0, 139)", + darkcyan: "rgb( 0, 139, 139)", + darkgoldenrod: "rgb(184, 134, 11)", + darkgray: "rgb(169, 169, 169)", + darkgreen: "rgb( 0, 100, 0)", + darkgrey: "rgb(169, 169, 169)", + darkkhaki: "rgb(189, 183, 107)", + darkmagenta: "rgb(139, 0, 139)", + darkolivegreen: "rgb( 85, 107, 47)", + darkorange: "rgb(255, 140, 0)", + darkorchid: "rgb(153, 50, 204)", + darkred: "rgb(139, 0, 0)", + darksalmon: "rgb(233, 150, 122)", + darkseagreen: "rgb(143, 188, 143)", + darkslateblue: "rgb( 72, 61, 139)", + darkslategray: "rgb( 47, 79, 79)", + darkslategrey: "rgb( 47, 79, 79)", + darkturquoise: "rgb( 0, 206, 209)", + darkviolet: "rgb(148, 0, 211)", + deeppink: "rgb(255, 20, 147)", + deepskyblue: "rgb( 0, 191, 255)", + dimgray: "rgb(105, 105, 105)", + dimgrey: "rgb(105, 105, 105)", + dodgerblue: "rgb( 30, 144, 255)", + firebrick: "rgb(178, 34, 34)", + floralwhite: "rgb(255, 250, 240)", + forestgreen: "rgb( 34, 139, 34)", + fuchsia: "rgb(255, 0, 255)", + gainsboro: "rgb(220, 220, 220)", + ghostwhite: "rgb(248, 248, 255)", + gold: "rgb(255, 215, 0)", + goldenrod: "rgb(218, 165, 32)", + gray: "rgb(128, 128, 128)", + grey: "rgb(128, 128, 128)", + green: "rgb( 0, 128, 0)", + greenyellow: "rgb(173, 255, 47)", + honeydew: "rgb(240, 255, 240)", + hotpink: "rgb(255, 105, 180)", + indianred: "rgb(205, 92, 92)", + indigo: "rgb( 75, 0, 130)", + ivory: "rgb(255, 255, 240)", + khaki: "rgb(240, 230, 140)", + lavender: "rgb(230, 230, 250)", + lavenderblush: "rgb(255, 240, 245)", + lawngreen: "rgb(124, 252, 0)", + lemonchiffon: "rgb(255, 250, 205)", + lightblue: "rgb(173, 216, 230)", + lightcoral: "rgb(240, 128, 128)", + lightcyan: "rgb(224, 255, 255)", + lightgoldenrodyellow: "rgb(250, 250, 210)", + lightgray: "rgb(211, 211, 211)", + lightgreen: "rgb(144, 238, 144)", + lightgrey: "rgb(211, 211, 211)", + lightpink: "rgb(255, 182, 193)", + lightsalmon: "rgb(255, 160, 122)", + lightseagreen: "rgb( 32, 178, 170)", + lightskyblue: "rgb(135, 206, 250)", + lightslategray: "rgb(119, 136, 153)", + lightslategrey: "rgb(119, 136, 153)", + lightsteelblue: "rgb(176, 196, 222)", + lightyellow: "rgb(255, 255, 224)", + lime: "rgb( 0, 255, 0)", + limegreen: "rgb( 50, 205, 50)", + linen: "rgb(250, 240, 230)", + magenta: "rgb(255, 0, 255)", + maroon: "rgb(128, 0, 0)", + mediumaquamarine: "rgb(102, 205, 170)", + mediumblue: "rgb( 0, 0, 205)", + mediumorchid: "rgb(186, 85, 211)", + mediumpurple: "rgb(147, 112, 219)", + mediumseagreen: "rgb( 60, 179, 113)", + mediumslateblue: "rgb(123, 104, 238)", + mediumspringgreen: "rgb( 0, 250, 154)", + mediumturquoise: "rgb( 72, 209, 204)", + mediumvioletred: "rgb(199, 21, 133)", + midnightblue: "rgb( 25, 25, 112)", + mintcream: "rgb(245, 255, 250)", + mistyrose: "rgb(255, 228, 225)", + moccasin: "rgb(255, 228, 181)", + navajowhite: "rgb(255, 222, 173)", + navy: "rgb( 0, 0, 128)", + oldlace: "rgb(253, 245, 230)", + olive: "rgb(128, 128, 0)", + olivedrab: "rgb(107, 142, 35)", + orange: "rgb(255, 165, 0)", + orangered: "rgb(255, 69, 0)", + orchid: "rgb(218, 112, 214)", + palegoldenrod: "rgb(238, 232, 170)", + palegreen: "rgb(152, 251, 152)", + paleturquoise: "rgb(175, 238, 238)", + palevioletred: "rgb(219, 112, 147)", + papayawhip: "rgb(255, 239, 213)", + peachpuff: "rgb(255, 218, 185)", + peru: "rgb(205, 133, 63)", + pink: "rgb(255, 192, 203)", + plum: "rgb(221, 160, 221)", + powderblue: "rgb(176, 224, 230)", + purple: "rgb(128, 0, 128)", + red: "rgb(255, 0, 0)", + rosybrown: "rgb(188, 143, 143)", + royalblue: "rgb( 65, 105, 225)", + saddlebrown: "rgb(139, 69, 19)", + salmon: "rgb(250, 128, 114)", + sandybrown: "rgb(244, 164, 96)", + seagreen: "rgb( 46, 139, 87)", + seashell: "rgb(255, 245, 238)", + sienna: "rgb(160, 82, 45)", + silver: "rgb(192, 192, 192)", + skyblue: "rgb(135, 206, 235)", + slateblue: "rgb(106, 90, 205)", + slategray: "rgb(112, 128, 144)", + slategrey: "rgb(112, 128, 144)", + snow: "rgb(255, 250, 250)", + springgreen: "rgb( 0, 255, 127)", + steelblue: "rgb( 70, 130, 180)", + tan: "rgb(210, 180, 140)", + teal: "rgb( 0, 128, 128)", + thistle: "rgb(216, 191, 216)", + tomato: "rgb(255, 99, 71)", + turquoise: "rgb( 64, 224, 208)", + violet: "rgb(238, 130, 238)", + wheat: "rgb(245, 222, 179)", + white: "rgb(255, 255, 255)", + whitesmoke: "rgb(245, 245, 245)", + yellow: "rgb(255, 255, 0)", + yellowgreen: "rgb(154, 205, 50)", + }; + L.jqplot.AxisLabelRenderer = function (ah) { + L.jqplot.ElemContainer.call(this); + this.axis; + this.show = true; + this.label = ""; + this.fontFamily = null; + this.fontSize = null; + this.textColor = null; + this._elem; + this.escapeHTML = false; + L.extend(true, this, ah); + }; + L.jqplot.AxisLabelRenderer.prototype = new L.jqplot.ElemContainer(); + L.jqplot.AxisLabelRenderer.prototype.constructor = + L.jqplot.AxisLabelRenderer; + L.jqplot.AxisLabelRenderer.prototype.init = function (ah) { + L.extend(true, this, ah); + }; + L.jqplot.AxisLabelRenderer.prototype.draw = function (ah, ai) { + if (this._elem) { + this._elem.emptyForce(); + this._elem = null; + } + this._elem = L( + '
', + ); + if (Number(this.label)) { + this._elem.css("white-space", "nowrap"); + } + if (!this.escapeHTML) { + this._elem.html(this.label); + } else { + this._elem.text(this.label); + } + if (this.fontFamily) { + this._elem.css("font-family", this.fontFamily); + } + if (this.fontSize) { + this._elem.css("font-size", this.fontSize); + } + if (this.textColor) { + this._elem.css("color", this.textColor); + } + return this._elem; + }; + L.jqplot.AxisLabelRenderer.prototype.pack = function () {}; + L.jqplot.AxisTickRenderer = function (ah) { + L.jqplot.ElemContainer.call(this); + this.mark = "outside"; + this.axis; + this.showMark = true; + this.showGridline = true; + this.isMinorTick = false; + this.size = 4; + this.markSize = 6; + this.show = true; + this.showLabel = true; + this.label = null; + this.value = null; + this._styles = {}; + this.formatter = L.jqplot.DefaultTickFormatter; + this.prefix = ""; + this.suffix = ""; + this.formatString = ""; + this.fontFamily; + this.fontSize; + this.textColor; + this.escapeHTML = false; + this._elem; + this._breakTick = false; + L.extend(true, this, ah); + }; + L.jqplot.AxisTickRenderer.prototype.init = function (ah) { + L.extend(true, this, ah); + }; + L.jqplot.AxisTickRenderer.prototype = new L.jqplot.ElemContainer(); + L.jqplot.AxisTickRenderer.prototype.constructor = L.jqplot.AxisTickRenderer; + L.jqplot.AxisTickRenderer.prototype.setTick = function (ah, aj, ai) { + this.value = ah; + this.axis = aj; + if (ai) { + this.isMinorTick = true; + } + return this; + }; + L.jqplot.AxisTickRenderer.prototype.draw = function () { + if (this.label === null) { + this.label = + this.prefix + + this.formatter(this.formatString, this.value) + + this.suffix; + } + var ai = { position: "absolute" }; + if (Number(this.label)) { + ai.whitSpace = "nowrap"; + } + if (this._elem) { + this._elem.emptyForce(); + this._elem = null; + } + this._elem = L(document.createElement("div")); + this._elem.addClass("jqplot-" + this.axis + "-tick"); + if (!this.escapeHTML) { + this._elem.html(this.label); + } else { + this._elem.text(this.label); + } + this._elem.css(ai); + for (var ah in this._styles) { + this._elem.css(ah, this._styles[ah]); + } + if (this.fontFamily) { + this._elem.css("font-family", this.fontFamily); + } + if (this.fontSize) { + this._elem.css("font-size", this.fontSize); + } + if (this.textColor) { + this._elem.css("color", this.textColor); + } + if (this._breakTick) { + this._elem.addClass("jqplot-breakTick"); + } + return this._elem; + }; + L.jqplot.DefaultTickFormatter = function (ah, ai) { + if (typeof ai == "number") { + if (!ah) { + ah = L.jqplot.config.defaultTickFormatString; + } + return L.jqplot.sprintf(ah, ai); + } else { + return String(ai); + } + }; + L.jqplot.PercentTickFormatter = function (ah, ai) { + if (typeof ai == "number") { + ai = 100 * ai; + if (!ah) { + ah = L.jqplot.config.defaultTickFormatString; + } + return L.jqplot.sprintf(ah, ai); + } else { + return String(ai); + } + }; + L.jqplot.AxisTickRenderer.prototype.pack = function () {}; + L.jqplot.CanvasGridRenderer = function () { + this.shadowRenderer = new L.jqplot.ShadowRenderer(); + }; + L.jqplot.CanvasGridRenderer.prototype.init = function (ai) { + this._ctx; + L.extend(true, this, ai); + var ah = { + lineJoin: "miter", + lineCap: "round", + fill: false, + isarc: false, + angle: this.shadowAngle, + offset: this.shadowOffset, + alpha: this.shadowAlpha, + depth: this.shadowDepth, + lineWidth: this.shadowWidth, + closePath: false, + strokeStyle: this.shadowColor, + }; + this.renderer.shadowRenderer.init(ah); + }; + L.jqplot.CanvasGridRenderer.prototype.createElement = function (ak) { + var aj; + if (this._elem) { + if ( + L.jqplot.use_excanvas && + window.G_vmlCanvasManager.uninitElement !== u + ) { + aj = this._elem.get(0); + window.G_vmlCanvasManager.uninitElement(aj); + aj = null; + } + this._elem.emptyForce(); + this._elem = null; + } + aj = ak.canvasManager.getCanvas(); + var ah = this._plotDimensions.width; + var ai = this._plotDimensions.height; + aj.width = ah; + aj.height = ai; + this._elem = L(aj); + this._elem.addClass("jqplot-grid-canvas"); + this._elem.css({ position: "absolute", left: 0, top: 0 }); + aj = ak.canvasManager.initCanvas(aj); + this._top = this._offsets.top; + this._bottom = ai - this._offsets.bottom; + this._left = this._offsets.left; + this._right = ah - this._offsets.right; + this._width = this._right - this._left; + this._height = this._bottom - this._top; + aj = null; + return this._elem; + }; + L.jqplot.CanvasGridRenderer.prototype.draw = function () { + this._ctx = this._elem.get(0).getContext("2d"); + var at = this._ctx; + var aw = this._axes; + at.save(); + at.clearRect( + 0, + 0, + this._plotDimensions.width, + this._plotDimensions.height, + ); + at.fillStyle = this.backgroundColor || this.background; + at.fillRect(this._left, this._top, this._width, this._height); + at.save(); + at.lineJoin = "miter"; + at.lineCap = "butt"; + at.lineWidth = this.gridLineWidth; + at.strokeStyle = this.gridLineColor; + var aA, az, ap, aq; + var am = ["xaxis", "yaxis", "x2axis", "y2axis"]; + for (var ay = 4; ay > 0; ay--) { + var aD = am[ay - 1]; + var ah = aw[aD]; + var aB = ah._ticks; + var ar = aB.length; + if (ah.show) { + if (ah.drawBaseline) { + var aC = {}; + if (ah.baselineWidth !== null) { + aC.lineWidth = ah.baselineWidth; + } + if (ah.baselineColor !== null) { + aC.strokeStyle = ah.baselineColor; + } + switch (aD) { + case "xaxis": + ao( + this._left, + this._bottom, + this._right, + this._bottom, + aC, + ); + break; + case "yaxis": + ao( + this._left, + this._bottom, + this._left, + this._top, + aC, + ); + break; + case "x2axis": + ao( + this._left, + this._bottom, + this._right, + this._bottom, + aC, + ); + break; + case "y2axis": + ao( + this._right, + this._bottom, + this._right, + this._top, + aC, + ); + break; + } + } + for (var au = ar; au > 0; au--) { + var an = aB[au - 1]; + if (an.show) { + var ak = Math.round(ah.u2p(an.value)) + 0.5; + switch (aD) { + case "xaxis": + if ( + an.showGridline && + this.drawGridlines && + ((!an.isMinorTick && + ah.drawMajorGridlines) || + (an.isMinorTick && + ah.drawMinorGridlines)) + ) { + ao(ak, this._top, ak, this._bottom); + } + if ( + an.showMark && + an.mark && + ((!an.isMinorTick && + ah.drawMajorTickMarks) || + (an.isMinorTick && + ah.drawMinorTickMarks)) + ) { + ap = an.markSize; + aq = an.mark; + var ak = Math.round(ah.u2p(an.value)) + 0.5; + switch (aq) { + case "outside": + aA = this._bottom; + az = this._bottom + ap; + break; + case "inside": + aA = this._bottom - ap; + az = this._bottom; + break; + case "cross": + aA = this._bottom - ap; + az = this._bottom + ap; + break; + default: + aA = this._bottom; + az = this._bottom + ap; + break; + } + if (this.shadow) { + this.renderer.shadowRenderer.draw( + at, + [ + [ak, aA], + [ak, az], + ], + { + lineCap: "butt", + lineWidth: this.gridLineWidth, + offset: + this.gridLineWidth * 0.75, + depth: 2, + fill: false, + closePath: false, + }, + ); + } + ao(ak, aA, ak, az); + } + break; + case "yaxis": + if ( + an.showGridline && + this.drawGridlines && + ((!an.isMinorTick && + ah.drawMajorGridlines) || + (an.isMinorTick && + ah.drawMinorGridlines)) + ) { + ao(this._right, ak, this._left, ak); + } + if ( + an.showMark && + an.mark && + ((!an.isMinorTick && + ah.drawMajorTickMarks) || + (an.isMinorTick && + ah.drawMinorTickMarks)) + ) { + ap = an.markSize; + aq = an.mark; + var ak = Math.round(ah.u2p(an.value)) + 0.5; + switch (aq) { + case "outside": + aA = this._left - ap; + az = this._left; + break; + case "inside": + aA = this._left; + az = this._left + ap; + break; + case "cross": + aA = this._left - ap; + az = this._left + ap; + break; + default: + aA = this._left - ap; + az = this._left; + break; + } + if (this.shadow) { + this.renderer.shadowRenderer.draw( + at, + [ + [aA, ak], + [az, ak], + ], + { + lineCap: "butt", + lineWidth: + this.gridLineWidth * 1.5, + offset: + this.gridLineWidth * 0.75, + fill: false, + closePath: false, + }, + ); + } + ao(aA, ak, az, ak, { + strokeStyle: ah.borderColor, + }); + } + break; + case "x2axis": + if ( + an.showGridline && + this.drawGridlines && + ((!an.isMinorTick && + ah.drawMajorGridlines) || + (an.isMinorTick && + ah.drawMinorGridlines)) + ) { + ao(ak, this._bottom, ak, this._top); + } + if ( + an.showMark && + an.mark && + ((!an.isMinorTick && + ah.drawMajorTickMarks) || + (an.isMinorTick && + ah.drawMinorTickMarks)) + ) { + ap = an.markSize; + aq = an.mark; + var ak = Math.round(ah.u2p(an.value)) + 0.5; + switch (aq) { + case "outside": + aA = this._top - ap; + az = this._top; + break; + case "inside": + aA = this._top; + az = this._top + ap; + break; + case "cross": + aA = this._top - ap; + az = this._top + ap; + break; + default: + aA = this._top - ap; + az = this._top; + break; + } + if (this.shadow) { + this.renderer.shadowRenderer.draw( + at, + [ + [ak, aA], + [ak, az], + ], + { + lineCap: "butt", + lineWidth: this.gridLineWidth, + offset: + this.gridLineWidth * 0.75, + depth: 2, + fill: false, + closePath: false, + }, + ); + } + ao(ak, aA, ak, az); + } + break; + case "y2axis": + if ( + an.showGridline && + this.drawGridlines && + ((!an.isMinorTick && + ah.drawMajorGridlines) || + (an.isMinorTick && + ah.drawMinorGridlines)) + ) { + ao(this._left, ak, this._right, ak); + } + if ( + an.showMark && + an.mark && + ((!an.isMinorTick && + ah.drawMajorTickMarks) || + (an.isMinorTick && + ah.drawMinorTickMarks)) + ) { + ap = an.markSize; + aq = an.mark; + var ak = Math.round(ah.u2p(an.value)) + 0.5; + switch (aq) { + case "outside": + aA = this._right; + az = this._right + ap; + break; + case "inside": + aA = this._right - ap; + az = this._right; + break; + case "cross": + aA = this._right - ap; + az = this._right + ap; + break; + default: + aA = this._right; + az = this._right + ap; + break; + } + if (this.shadow) { + this.renderer.shadowRenderer.draw( + at, + [ + [aA, ak], + [az, ak], + ], + { + lineCap: "butt", + lineWidth: + this.gridLineWidth * 1.5, + offset: + this.gridLineWidth * 0.75, + fill: false, + closePath: false, + }, + ); + } + ao(aA, ak, az, ak, { + strokeStyle: ah.borderColor, + }); + } + break; + default: + break; + } + } + } + an = null; + } + ah = null; + aB = null; + } + am = [ + "y3axis", + "y4axis", + "y5axis", + "y6axis", + "y7axis", + "y8axis", + "y9axis", + "yMidAxis", + ]; + for (var ay = 7; ay > 0; ay--) { + var ah = aw[am[ay - 1]]; + var aB = ah._ticks; + if (ah.show) { + var ai = aB[ah.numberTicks - 1]; + var al = aB[0]; + var aj = ah.getLeft(); + var av = [ + [aj, ai.getTop() + ai.getHeight() / 2], + [aj, al.getTop() + al.getHeight() / 2 + 1], + ]; + if (this.shadow) { + this.renderer.shadowRenderer.draw(at, av, { + lineCap: "butt", + fill: false, + closePath: false, + }); + } + ao(av[0][0], av[0][1], av[1][0], av[1][1], { + lineCap: "butt", + strokeStyle: ah.borderColor, + lineWidth: ah.borderWidth, + }); + for (var au = aB.length; au > 0; au--) { + var an = aB[au - 1]; + ap = an.markSize; + aq = an.mark; + var ak = Math.round(ah.u2p(an.value)) + 0.5; + if (an.showMark && an.mark) { + switch (aq) { + case "outside": + aA = aj; + az = aj + ap; + break; + case "inside": + aA = aj - ap; + az = aj; + break; + case "cross": + aA = aj - ap; + az = aj + ap; + break; + default: + aA = aj; + az = aj + ap; + break; + } + av = [ + [aA, ak], + [az, ak], + ]; + if (this.shadow) { + this.renderer.shadowRenderer.draw(at, av, { + lineCap: "butt", + lineWidth: this.gridLineWidth * 1.5, + offset: this.gridLineWidth * 0.75, + fill: false, + closePath: false, + }); + } + ao(aA, ak, az, ak, { strokeStyle: ah.borderColor }); + } + an = null; + } + al = null; + } + ah = null; + aB = null; + } + at.restore(); + function ao(aH, aG, aE, ax, aF) { + at.save(); + aF = aF || {}; + if (aF.lineWidth == null || aF.lineWidth != 0) { + L.extend(true, at, aF); + at.beginPath(); + at.moveTo(aH, aG); + at.lineTo(aE, ax); + at.stroke(); + at.restore(); + } + } + if (this.shadow) { + var av = [ + [this._left, this._bottom], + [this._right, this._bottom], + [this._right, this._top], + ]; + this.renderer.shadowRenderer.draw(at, av); + } + if (this.borderWidth != 0 && this.drawBorder) { + ao(this._left, this._top, this._right, this._top, { + lineCap: "round", + strokeStyle: aw.x2axis.borderColor, + lineWidth: aw.x2axis.borderWidth, + }); + ao(this._right, this._top, this._right, this._bottom, { + lineCap: "round", + strokeStyle: aw.y2axis.borderColor, + lineWidth: aw.y2axis.borderWidth, + }); + ao(this._right, this._bottom, this._left, this._bottom, { + lineCap: "round", + strokeStyle: aw.xaxis.borderColor, + lineWidth: aw.xaxis.borderWidth, + }); + ao(this._left, this._bottom, this._left, this._top, { + lineCap: "round", + strokeStyle: aw.yaxis.borderColor, + lineWidth: aw.yaxis.borderWidth, + }); + } + at.restore(); + at = null; + aw = null; + }; + L.jqplot.DivTitleRenderer = function () {}; + L.jqplot.DivTitleRenderer.prototype.init = function (ah) { + L.extend(true, this, ah); + }; + L.jqplot.DivTitleRenderer.prototype.draw = function () { + if (this._elem) { + this._elem.emptyForce(); + this._elem = null; + } + var ak = this.renderer; + var aj = document.createElement("div"); + this._elem = L(aj); + this._elem.addClass("jqplot-title"); + if (!this.text) { + this.show = false; + this._elem.height(0); + this._elem.width(0); + } else { + if (this.text) { + var ah; + if (this.color) { + ah = this.color; + } else { + if (this.textColor) { + ah = this.textColor; + } + } + var ai = { position: "absolute", top: "0px", left: "0px" }; + if (this._plotWidth) { + ai.width = this._plotWidth + "px"; + } + if (this.fontSize) { + ai.fontSize = this.fontSize; + } + if (typeof this.textAlign === "string") { + ai.textAlign = this.textAlign; + } else { + ai.textAlign = "center"; + } + if (ah) { + ai.color = ah; + } + if (this.paddingBottom) { + ai.paddingBottom = this.paddingBottom; + } + if (this.fontFamily) { + ai.fontFamily = this.fontFamily; + } + this._elem.css(ai); + if (this.escapeHtml) { + this._elem.text(this.text); + } else { + this._elem.html(this.text); + } + } + } + aj = null; + return this._elem; + }; + L.jqplot.DivTitleRenderer.prototype.pack = function () {}; + var r = 0.1; + L.jqplot.LinePattern = function (aw, aq) { + var ap = { + dotted: [r, L.jqplot.config.dotGapLength], + dashed: [L.jqplot.config.dashLength, L.jqplot.config.gapLength], + solid: null, + }; + if (typeof aq === "string") { + if (aq[0] === "." || aq[0] === "-") { + var ax = aq; + aq = []; + for (var ao = 0, al = ax.length; ao < al; ao++) { + if (ax[ao] === ".") { + aq.push(r); + } else { + if (ax[ao] === "-") { + aq.push(L.jqplot.config.dashLength); + } else { + continue; + } + } + aq.push(L.jqplot.config.gapLength); + } + } else { + aq = ap[aq]; + } + } + if (!(aq && aq.length)) { + return aw; + } + var ak = 0; + var ar = aq[0]; + var au = 0; + var at = 0; + var an = 0; + var ah = 0; + var av = function (ay, az) { + aw.moveTo(ay, az); + au = ay; + at = az; + an = ay; + ah = az; + }; + var aj = function (ay, aE) { + var aC = aw.lineWidth; + var aA = ay - au; + var az = aE - at; + var aB = Math.sqrt(aA * aA + az * az); + if (aB > 0 && aC > 0) { + aA /= aB; + az /= aB; + while (true) { + var aD = aC * ar; + if (aD < aB) { + au += aD * aA; + at += aD * az; + if ((ak & 1) == 0) { + aw.lineTo(au, at); + } else { + aw.moveTo(au, at); + } + aB -= aD; + ak++; + if (ak >= aq.length) { + ak = 0; + } + ar = aq[ak]; + } else { + au = ay; + at = aE; + if ((ak & 1) == 0) { + aw.lineTo(au, at); + } else { + aw.moveTo(au, at); + } + ar -= aB / aC; + break; + } + } + } + }; + var ai = function () { + aw.beginPath(); + }; + var am = function () { + aj(an, ah); + }; + return { moveTo: av, lineTo: aj, beginPath: ai, closePath: am }; + }; + L.jqplot.LineRenderer = function () { + this.shapeRenderer = new L.jqplot.ShapeRenderer(); + this.shadowRenderer = new L.jqplot.ShadowRenderer(); + }; + L.jqplot.LineRenderer.prototype.init = function (ai, an) { + ai = ai || {}; + this._type = "line"; + this.renderer.animation = { + show: false, + direction: "left", + speed: 2500, + _supported: true, + }; + this.renderer.smooth = false; + this.renderer.tension = null; + this.renderer.constrainSmoothing = true; + this.renderer._smoothedData = []; + this.renderer._smoothedPlotData = []; + this.renderer._hiBandGridData = []; + this.renderer._lowBandGridData = []; + this.renderer._hiBandSmoothedData = []; + this.renderer._lowBandSmoothedData = []; + this.renderer.bandData = []; + this.renderer.bands = { + show: false, + hiData: [], + lowData: [], + color: this.color, + showLines: false, + fill: true, + fillColor: null, + _min: null, + _max: null, + interval: "3%", + }; + var al = { + highlightMouseOver: ai.highlightMouseOver, + highlightMouseDown: ai.highlightMouseDown, + highlightColor: ai.highlightColor, + }; + delete ai.highlightMouseOver; + delete ai.highlightMouseDown; + delete ai.highlightColor; + L.extend(true, this.renderer, ai); + this.renderer.options = ai; + if ( + this.renderer.bandData.length > 1 && + (!ai.bands || ai.bands.show == null) + ) { + this.renderer.bands.show = true; + } else { + if ( + ai.bands && + ai.bands.show == null && + ai.bands.interval != null + ) { + this.renderer.bands.show = true; + } + } + if (this.fill) { + this.renderer.bands.show = false; + } + if (this.renderer.bands.show) { + this.renderer.initBands.call(this, this.renderer.options, an); + } + if (this._stack) { + this.renderer.smooth = false; + } + var am = { + lineJoin: this.lineJoin, + lineCap: this.lineCap, + fill: this.fill, + isarc: false, + strokeStyle: this.color, + fillStyle: this.fillColor, + lineWidth: this.lineWidth, + linePattern: this.linePattern, + closePath: this.fill, + }; + this.renderer.shapeRenderer.init(am); + var aj = ai.shadowOffset; + if (aj == null) { + if (this.lineWidth > 2.5) { + aj = + 1.25 * + (1 + + (Math.atan(this.lineWidth / 2.5) / 0.785398163 - 1) * + 0.6); + } else { + aj = (1.25 * Math.atan(this.lineWidth / 2.5)) / 0.785398163; + } + } + var ah = { + lineJoin: this.lineJoin, + lineCap: this.lineCap, + fill: this.fill, + isarc: false, + angle: this.shadowAngle, + offset: aj, + alpha: this.shadowAlpha, + depth: this.shadowDepth, + lineWidth: this.lineWidth, + linePattern: this.linePattern, + closePath: this.fill, + }; + this.renderer.shadowRenderer.init(ah); + this._areaPoints = []; + this._boundingBox = [[], []]; + if ((!this.isTrendline && this.fill) || this.renderer.bands.show) { + this.highlightMouseOver = true; + this.highlightMouseDown = false; + this.highlightColor = null; + if (al.highlightMouseDown && al.highlightMouseOver == null) { + al.highlightMouseOver = false; + } + L.extend(true, this, { + highlightMouseOver: al.highlightMouseOver, + highlightMouseDown: al.highlightMouseDown, + highlightColor: al.highlightColor, + }); + if (!this.highlightColor) { + var ak = this.renderer.bands.show + ? this.renderer.bands.fillColor + : this.fillColor; + this.highlightColor = L.jqplot.computeHighlightColors(ak); + } + if (this.highlighter) { + this.highlighter.show = false; + } + } + if (!this.isTrendline && an) { + an.plugins.lineRenderer = {}; + an.postInitHooks.addOnce(z); + an.postDrawHooks.addOnce(af); + an.eventListenerHooks.addOnce("jqplotMouseMove", h); + an.eventListenerHooks.addOnce("jqplotMouseDown", e); + an.eventListenerHooks.addOnce("jqplotMouseUp", ad); + an.eventListenerHooks.addOnce("jqplotClick", g); + an.eventListenerHooks.addOnce("jqplotRightClick", s); + } + }; + L.jqplot.LineRenderer.prototype.initBands = function (ak, av) { + var al = ak.bandData || []; + var an = this.renderer.bands; + an.hiData = []; + an.lowData = []; + var aB = this.data; + an._max = null; + an._min = null; + if (al.length == 2) { + if (L.isArray(al[0][0])) { + var ao; + var ah = 0, + ar = 0; + for (var aw = 0, at = al[0].length; aw < at; aw++) { + ao = al[0][aw]; + if ((ao[1] != null && ao[1] > an._max) || an._max == null) { + an._max = ao[1]; + } + if ((ao[1] != null && ao[1] < an._min) || an._min == null) { + an._min = ao[1]; + } + } + for (var aw = 0, at = al[1].length; aw < at; aw++) { + ao = al[1][aw]; + if ((ao[1] != null && ao[1] > an._max) || an._max == null) { + an._max = ao[1]; + ar = 1; + } + if ((ao[1] != null && ao[1] < an._min) || an._min == null) { + an._min = ao[1]; + ah = 1; + } + } + if (ar === ah) { + an.show = false; + } + an.hiData = al[ar]; + an.lowData = al[ah]; + } else { + if (al[0].length === aB.length && al[1].length === aB.length) { + var aj = al[0][0] > al[1][0] ? 0 : 1; + var aC = aj ? 0 : 1; + for (var aw = 0, at = aB.length; aw < at; aw++) { + an.hiData.push([aB[aw][0], al[aj][aw]]); + an.lowData.push([aB[aw][0], al[aC][aw]]); + } + } else { + an.show = false; + } + } + } else { + if (al.length > 2 && !L.isArray(al[0][0])) { + var aj = al[0][0] > al[0][1] ? 0 : 1; + var aC = aj ? 0 : 1; + for (var aw = 0, at = al.length; aw < at; aw++) { + an.hiData.push([aB[aw][0], al[aw][aj]]); + an.lowData.push([aB[aw][0], al[aw][aC]]); + } + } else { + var aq = an.interval; + var aA = null; + var az = null; + var ai = null; + var au = null; + if (L.isArray(aq)) { + aA = aq[0]; + az = aq[1]; + } else { + aA = aq; + } + if (isNaN(aA)) { + if (aA.charAt(aA.length - 1) === "%") { + ai = "multiply"; + aA = parseFloat(aA) / 100 + 1; + } + } else { + aA = parseFloat(aA); + ai = "add"; + } + if (az !== null && isNaN(az)) { + if (az.charAt(az.length - 1) === "%") { + au = "multiply"; + az = parseFloat(az) / 100 + 1; + } + } else { + if (az !== null) { + az = parseFloat(az); + au = "add"; + } + } + if (aA !== null) { + if (az === null) { + az = -aA; + au = ai; + if (au === "multiply") { + az += 2; + } + } + if (aA < az) { + var ax = aA; + aA = az; + az = ax; + ax = ai; + ai = au; + au = ax; + } + for (var aw = 0, at = aB.length; aw < at; aw++) { + switch (ai) { + case "add": + an.hiData.push([aB[aw][0], aB[aw][1] + aA]); + break; + case "multiply": + an.hiData.push([aB[aw][0], aB[aw][1] * aA]); + break; + } + switch (au) { + case "add": + an.lowData.push([aB[aw][0], aB[aw][1] + az]); + break; + case "multiply": + an.lowData.push([aB[aw][0], aB[aw][1] * az]); + break; + } + } + } else { + an.show = false; + } + } + } + var am = an.hiData; + var ap = an.lowData; + for (var aw = 0, at = am.length; aw < at; aw++) { + if ((am[aw][1] != null && am[aw][1] > an._max) || an._max == null) { + an._max = am[aw][1]; + } + } + for (var aw = 0, at = ap.length; aw < at; aw++) { + if ((ap[aw][1] != null && ap[aw][1] < an._min) || an._min == null) { + an._min = ap[aw][1]; + } + } + if (an.fillColor === null) { + var ay = L.jqplot.getColorComponents(an.color); + ay[3] = ay[3] * 0.5; + an.fillColor = + "rgba(" + + ay[0] + + ", " + + ay[1] + + ", " + + ay[2] + + ", " + + ay[3] + + ")"; + } + }; + function K(ai, ah) { + return (3.4182054 + ah) * Math.pow(ai, -0.3534992); + } + function n(aj, ai) { + var ah = Math.sqrt( + Math.pow(ai[0] - aj[0], 2) + Math.pow(ai[1] - aj[1], 2), + ); + return 5.7648 * Math.log(ah) + 7.4456; + } + function A(ah) { + var ai = (Math.exp(2 * ah) - 1) / (Math.exp(2 * ah) + 1); + return ai; + } + function J(aJ) { + var at = this.renderer.smooth; + var aD = this.canvas.getWidth(); + var an = this._xaxis.series_p2u; + var aG = this._yaxis.series_p2u; + var aF = null; + var am = null; + var az = aJ.length / aD; + var aj = []; + var ay = []; + if (!isNaN(parseFloat(at))) { + aF = parseFloat(at); + } else { + aF = K(az, 0.5); + } + var aw = []; + var ak = []; + for (var aE = 0, aA = aJ.length; aE < aA; aE++) { + aw.push(aJ[aE][1]); + ak.push(aJ[aE][0]); + } + function av(aK, aL) { + if (aK - aL == 0) { + return Math.pow(10, 10); + } else { + return aK - aL; + } + } + var ax, ar, aq, ap; + var ah = aJ.length - 1; + for (var al = 1, aB = aJ.length; al < aB; al++) { + var ai = []; + var au = []; + for (var aC = 0; aC < 2; aC++) { + var aE = al - 1 + aC; + if (aE == 0 || aE == ah) { + ai[aC] = Math.pow(10, 10); + } else { + if (aw[aE + 1] - aw[aE] == 0 || aw[aE] - aw[aE - 1] == 0) { + ai[aC] = 0; + } else { + if ( + (ak[aE + 1] - ak[aE]) / (aw[aE + 1] - aw[aE]) + + (ak[aE] - ak[aE - 1]) / (aw[aE] - aw[aE - 1]) == + 0 + ) { + ai[aC] = 0; + } else { + if ( + (aw[aE + 1] - aw[aE]) * (aw[aE] - aw[aE - 1]) < + 0 + ) { + ai[aC] = 0; + } else { + ai[aC] = + 2 / + (av(ak[aE + 1], ak[aE]) / + (aw[aE + 1] - aw[aE]) + + av(ak[aE], ak[aE - 1]) / + (aw[aE] - aw[aE - 1])); + } + } + } + } + } + if (al == 1) { + ai[0] = + ((3 / 2) * (aw[1] - aw[0])) / av(ak[1], ak[0]) - ai[1] / 2; + } else { + if (al == ah) { + ai[1] = + ((3 / 2) * (aw[ah] - aw[ah - 1])) / + av(ak[ah], ak[ah - 1]) - + ai[0] / 2; + } + } + au[0] = + (-2 * (ai[1] + 2 * ai[0])) / av(ak[al], ak[al - 1]) + + (6 * (aw[al] - aw[al - 1])) / + Math.pow(av(ak[al], ak[al - 1]), 2); + au[1] = + (2 * (2 * ai[1] + ai[0])) / av(ak[al], ak[al - 1]) - + (6 * (aw[al] - aw[al - 1])) / + Math.pow(av(ak[al], ak[al - 1]), 2); + ap = ((1 / 6) * (au[1] - au[0])) / av(ak[al], ak[al - 1]); + aq = + ((1 / 2) * (ak[al] * au[0] - ak[al - 1] * au[1])) / + av(ak[al], ak[al - 1]); + ar = + (aw[al] - + aw[al - 1] - + aq * (Math.pow(ak[al], 2) - Math.pow(ak[al - 1], 2)) - + ap * (Math.pow(ak[al], 3) - Math.pow(ak[al - 1], 3))) / + av(ak[al], ak[al - 1]); + ax = + aw[al - 1] - + ar * ak[al - 1] - + aq * Math.pow(ak[al - 1], 2) - + ap * Math.pow(ak[al - 1], 3); + var aI = (ak[al] - ak[al - 1]) / aF; + var aH, ao; + for (var aC = 0, aA = aF; aC < aA; aC++) { + aH = []; + ao = ak[al - 1] + aC * aI; + aH.push(ao); + aH.push( + ax + ar * ao + aq * Math.pow(ao, 2) + ap * Math.pow(ao, 3), + ); + aj.push(aH); + ay.push([an(aH[0]), aG(aH[1])]); + } + } + aj.push(aJ[aE]); + ay.push([an(aJ[aE][0]), aG(aJ[aE][1])]); + return [aj, ay]; + } + function F(ap) { + var ao = this.renderer.smooth; + var aU = this.renderer.tension; + var ah = this.canvas.getWidth(); + var aH = this._xaxis.series_p2u; + var aq = this._yaxis.series_p2u; + var aI = null; + var aJ = null; + var aT = null; + var aO = null; + var aM = null; + var at = null; + var aR = null; + var am = null; + var aK, aL, aD, aC, aA, ay; + var ak, ai, av, au; + var aB, az, aN; + var aw = []; + var aj = []; + var al = ap.length / ah; + var aS, ax, aF, aG, aE; + var ar = []; + var an = []; + if (!isNaN(parseFloat(ao))) { + aI = parseFloat(ao); + } else { + aI = K(al, 0.5); + } + if (!isNaN(parseFloat(aU))) { + aU = parseFloat(aU); + } + for (var aQ = 0, aP = ap.length - 1; aQ < aP; aQ++) { + if (aU === null) { + at = Math.abs( + (ap[aQ + 1][1] - ap[aQ][1]) / (ap[aQ + 1][0] - ap[aQ][0]), + ); + aS = 0.3; + ax = 0.6; + aF = (ax - aS) / 2; + aG = 2.5; + aE = -1.4; + am = at / aG + aE; + aO = aF * A(am) - aF * A(aE) + aS; + if (aQ > 0) { + aR = Math.abs( + (ap[aQ][1] - ap[aQ - 1][1]) / + (ap[aQ][0] - ap[aQ - 1][0]), + ); + } + am = aR / aG + aE; + aM = aF * A(am) - aF * A(aE) + aS; + aT = (aO + aM) / 2; + } else { + aT = aU; + } + for (aK = 0; aK < aI; aK++) { + aL = aK / aI; + aD = (1 + 2 * aL) * Math.pow(1 - aL, 2); + aC = aL * Math.pow(1 - aL, 2); + aA = Math.pow(aL, 2) * (3 - 2 * aL); + ay = Math.pow(aL, 2) * (aL - 1); + if (ap[aQ - 1]) { + ak = aT * (ap[aQ + 1][0] - ap[aQ - 1][0]); + ai = aT * (ap[aQ + 1][1] - ap[aQ - 1][1]); + } else { + ak = aT * (ap[aQ + 1][0] - ap[aQ][0]); + ai = aT * (ap[aQ + 1][1] - ap[aQ][1]); + } + if (ap[aQ + 2]) { + av = aT * (ap[aQ + 2][0] - ap[aQ][0]); + au = aT * (ap[aQ + 2][1] - ap[aQ][1]); + } else { + av = aT * (ap[aQ + 1][0] - ap[aQ][0]); + au = aT * (ap[aQ + 1][1] - ap[aQ][1]); + } + aB = aD * ap[aQ][0] + aA * ap[aQ + 1][0] + aC * ak + ay * av; + az = aD * ap[aQ][1] + aA * ap[aQ + 1][1] + aC * ai + ay * au; + aN = [aB, az]; + ar.push(aN); + an.push([aH(aB), aq(az)]); + } + } + ar.push(ap[aP]); + an.push([aH(ap[aP][0]), aq(ap[aP][1])]); + return [ar, an]; + } + L.jqplot.LineRenderer.prototype.setGridData = function (ap) { + var al = this._xaxis.series_u2p; + var ah = this._yaxis.series_u2p; + var am = this._plotData; + var aq = this._prevPlotData; + this.gridData = []; + this._prevGridData = []; + this.renderer._smoothedData = []; + this.renderer._smoothedPlotData = []; + this.renderer._hiBandGridData = []; + this.renderer._lowBandGridData = []; + this.renderer._hiBandSmoothedData = []; + this.renderer._lowBandSmoothedData = []; + var ak = this.renderer.bands; + var ai = false; + for (var an = 0, aj = am.length; an < aj; an++) { + if (am[an][0] != null && am[an][1] != null) { + this.gridData.push([ + al.call(this._xaxis, am[an][0]), + ah.call(this._yaxis, am[an][1]), + ]); + } else { + if (am[an][0] == null) { + ai = true; + this.gridData.push([null, ah.call(this._yaxis, am[an][1])]); + } else { + if (am[an][1] == null) { + ai = true; + this.gridData.push([ + al.call(this._xaxis, am[an][0]), + null, + ]); + } + } + } + if (aq[an] != null && aq[an][0] != null && aq[an][1] != null) { + this._prevGridData.push([ + al.call(this._xaxis, aq[an][0]), + ah.call(this._yaxis, aq[an][1]), + ]); + } else { + if (aq[an] != null && aq[an][0] == null) { + this._prevGridData.push([ + null, + ah.call(this._yaxis, aq[an][1]), + ]); + } else { + if ( + aq[an] != null && + aq[an][0] != null && + aq[an][1] == null + ) { + this._prevGridData.push([ + al.call(this._xaxis, aq[an][0]), + null, + ]); + } + } + } + } + if (ai) { + this.renderer.smooth = false; + if (this._type === "line") { + ak.show = false; + } + } + if (this._type === "line" && ak.show) { + for (var an = 0, aj = ak.hiData.length; an < aj; an++) { + this.renderer._hiBandGridData.push([ + al.call(this._xaxis, ak.hiData[an][0]), + ah.call(this._yaxis, ak.hiData[an][1]), + ]); + } + for (var an = 0, aj = ak.lowData.length; an < aj; an++) { + this.renderer._lowBandGridData.push([ + al.call(this._xaxis, ak.lowData[an][0]), + ah.call(this._yaxis, ak.lowData[an][1]), + ]); + } + } + if ( + this._type === "line" && + this.renderer.smooth && + this.gridData.length > 2 + ) { + var ao; + if (this.renderer.constrainSmoothing) { + ao = J.call(this, this.gridData); + this.renderer._smoothedData = ao[0]; + this.renderer._smoothedPlotData = ao[1]; + if (ak.show) { + ao = J.call(this, this.renderer._hiBandGridData); + this.renderer._hiBandSmoothedData = ao[0]; + ao = J.call(this, this.renderer._lowBandGridData); + this.renderer._lowBandSmoothedData = ao[0]; + } + ao = null; + } else { + ao = F.call(this, this.gridData); + this.renderer._smoothedData = ao[0]; + this.renderer._smoothedPlotData = ao[1]; + if (ak.show) { + ao = F.call(this, this.renderer._hiBandGridData); + this.renderer._hiBandSmoothedData = ao[0]; + ao = F.call(this, this.renderer._lowBandGridData); + this.renderer._lowBandSmoothedData = ao[0]; + } + ao = null; + } + } + }; + L.jqplot.LineRenderer.prototype.makeGridData = function (ao, aq) { + var am = this._xaxis.series_u2p; + var ah = this._yaxis.series_u2p; + var ar = []; + var aj = []; + this.renderer._smoothedData = []; + this.renderer._smoothedPlotData = []; + this.renderer._hiBandGridData = []; + this.renderer._lowBandGridData = []; + this.renderer._hiBandSmoothedData = []; + this.renderer._lowBandSmoothedData = []; + var al = this.renderer.bands; + var ai = false; + for (var an = 0; an < ao.length; an++) { + if (ao[an][0] != null && ao[an][1] != null) { + ar.push([ + am.call(this._xaxis, ao[an][0]), + ah.call(this._yaxis, ao[an][1]), + ]); + } else { + if (ao[an][0] == null) { + ai = true; + ar.push([null, ah.call(this._yaxis, ao[an][1])]); + } else { + if (ao[an][1] == null) { + ai = true; + ar.push([am.call(this._xaxis, ao[an][0]), null]); + } + } + } + } + if (ai) { + this.renderer.smooth = false; + if (this._type === "line") { + al.show = false; + } + } + if (this._type === "line" && al.show) { + for (var an = 0, ak = al.hiData.length; an < ak; an++) { + this.renderer._hiBandGridData.push([ + am.call(this._xaxis, al.hiData[an][0]), + ah.call(this._yaxis, al.hiData[an][1]), + ]); + } + for (var an = 0, ak = al.lowData.length; an < ak; an++) { + this.renderer._lowBandGridData.push([ + am.call(this._xaxis, al.lowData[an][0]), + ah.call(this._yaxis, al.lowData[an][1]), + ]); + } + } + if (this._type === "line" && this.renderer.smooth && ar.length > 2) { + var ap; + if (this.renderer.constrainSmoothing) { + ap = J.call(this, ar); + this.renderer._smoothedData = ap[0]; + this.renderer._smoothedPlotData = ap[1]; + if (al.show) { + ap = J.call(this, this.renderer._hiBandGridData); + this.renderer._hiBandSmoothedData = ap[0]; + ap = J.call(this, this.renderer._lowBandGridData); + this.renderer._lowBandSmoothedData = ap[0]; + } + ap = null; + } else { + ap = F.call(this, ar); + this.renderer._smoothedData = ap[0]; + this.renderer._smoothedPlotData = ap[1]; + if (al.show) { + ap = F.call(this, this.renderer._hiBandGridData); + this.renderer._hiBandSmoothedData = ap[0]; + ap = F.call(this, this.renderer._lowBandGridData); + this.renderer._lowBandSmoothedData = ap[0]; + } + ap = null; + } + } + return ar; + }; + L.jqplot.LineRenderer.prototype.draw = function (ax, aI, ai, aB) { + var aC; + var aq = L.extend(true, {}, ai); + var ak = aq.shadow != u ? aq.shadow : this.shadow; + var aJ = aq.showLine != u ? aq.showLine : this.showLine; + var aA = aq.fill != u ? aq.fill : this.fill; + var ah = aq.fillAndStroke != u ? aq.fillAndStroke : this.fillAndStroke; + var ar, ay, av, aE; + ax.save(); + if (aI.length) { + if (aJ) { + if (aA) { + if (this.fillToZero) { + var aF = this.negativeColor; + if (!this.useNegativeColors) { + aF = aq.fillStyle; + } + var ao = false; + var ap = aq.fillStyle; + if (ah) { + var aH = aI.slice(0); + } + if (this.index == 0 || !this._stack) { + var aw = []; + var aL = this.renderer.smooth + ? this.renderer._smoothedPlotData + : this._plotData; + this._areaPoints = []; + var aG = this._yaxis.series_u2p(this.fillToValue); + var aj = this._xaxis.series_u2p(this.fillToValue); + aq.closePath = true; + if (this.fillAxis == "y") { + aw.push([aI[0][0], aG]); + this._areaPoints.push([aI[0][0], aG]); + for (var aC = 0; aC < aI.length - 1; aC++) { + aw.push(aI[aC]); + this._areaPoints.push(aI[aC]); + if (aL[aC][1] * aL[aC + 1][1] <= 0) { + if (aL[aC][1] < 0) { + ao = true; + aq.fillStyle = aF; + } else { + ao = false; + aq.fillStyle = ap; + } + var an = + aI[aC][0] + + ((aI[aC + 1][0] - aI[aC][0]) * + (aG - aI[aC][1])) / + (aI[aC + 1][1] - aI[aC][1]); + aw.push([an, aG]); + this._areaPoints.push([an, aG]); + if (ak) { + this.renderer.shadowRenderer.draw( + ax, + aw, + aq, + ); + } + this.renderer.shapeRenderer.draw( + ax, + aw, + aq, + ); + aw = [[an, aG]]; + } + } + if (aL[aI.length - 1][1] < 0) { + ao = true; + aq.fillStyle = aF; + } else { + ao = false; + aq.fillStyle = ap; + } + aw.push(aI[aI.length - 1]); + this._areaPoints.push(aI[aI.length - 1]); + aw.push([aI[aI.length - 1][0], aG]); + this._areaPoints.push([ + aI[aI.length - 1][0], + aG, + ]); + } + if (ak) { + this.renderer.shadowRenderer.draw(ax, aw, aq); + } + this.renderer.shapeRenderer.draw(ax, aw, aq); + } else { + var au = this._prevGridData; + for (var aC = au.length; aC > 0; aC--) { + aI.push(au[aC - 1]); + } + if (ak) { + this.renderer.shadowRenderer.draw(ax, aI, aq); + } + this._areaPoints = aI; + this.renderer.shapeRenderer.draw(ax, aI, aq); + } + } else { + if (ah) { + var aH = aI.slice(0); + } + if (this.index == 0 || !this._stack) { + var al = ax.canvas.height; + aI.unshift([aI[0][0], al]); + var aD = aI.length; + aI.push([aI[aD - 1][0], al]); + } else { + var au = this._prevGridData; + for (var aC = au.length; aC > 0; aC--) { + aI.push(au[aC - 1]); + } + } + this._areaPoints = aI; + if (ak) { + this.renderer.shadowRenderer.draw(ax, aI, aq); + } + this.renderer.shapeRenderer.draw(ax, aI, aq); + } + if (ah) { + var az = L.extend(true, {}, aq, { + fill: false, + closePath: false, + }); + this.renderer.shapeRenderer.draw(ax, aH, az); + if (this.markerRenderer.show) { + if (this.renderer.smooth) { + aH = this.gridData; + } + for (aC = 0; aC < aH.length; aC++) { + this.markerRenderer.draw( + aH[aC][0], + aH[aC][1], + ax, + aq.markerOptions, + ); + } + } + } + } else { + if (this.renderer.bands.show) { + var am; + var aK = L.extend(true, {}, aq); + if (this.renderer.bands.showLines) { + am = this.renderer.smooth + ? this.renderer._hiBandSmoothedData + : this.renderer._hiBandGridData; + this.renderer.shapeRenderer.draw(ax, am, aq); + am = this.renderer.smooth + ? this.renderer._lowBandSmoothedData + : this.renderer._lowBandGridData; + this.renderer.shapeRenderer.draw(ax, am, aK); + } + if (this.renderer.bands.fill) { + if (this.renderer.smooth) { + am = this.renderer._hiBandSmoothedData.concat( + this.renderer._lowBandSmoothedData.reverse(), + ); + } else { + am = this.renderer._hiBandGridData.concat( + this.renderer._lowBandGridData.reverse(), + ); + } + this._areaPoints = am; + aK.closePath = true; + aK.fill = true; + aK.fillStyle = this.renderer.bands.fillColor; + this.renderer.shapeRenderer.draw(ax, am, aK); + } + } + if (ak) { + this.renderer.shadowRenderer.draw(ax, aI, aq); + } + this.renderer.shapeRenderer.draw(ax, aI, aq); + } + } + var ar = (av = ay = aE = null); + for (aC = 0; aC < this._areaPoints.length; aC++) { + var at = this._areaPoints[aC]; + if (ar > at[0] || ar == null) { + ar = at[0]; + } + if (aE < at[1] || aE == null) { + aE = at[1]; + } + if (av < at[0] || av == null) { + av = at[0]; + } + if (ay > at[1] || ay == null) { + ay = at[1]; + } + } + if (this.type === "line" && this.renderer.bands.show) { + aE = this._yaxis.series_u2p(this.renderer.bands._min); + ay = this._yaxis.series_u2p(this.renderer.bands._max); + } + this._boundingBox = [ + [ar, aE], + [av, ay], + ]; + if (this.markerRenderer.show && !aA) { + if (this.renderer.smooth) { + aI = this.gridData; + } + for (aC = 0; aC < aI.length; aC++) { + if (aI[aC][0] != null && aI[aC][1] != null) { + this.markerRenderer.draw( + aI[aC][0], + aI[aC][1], + ax, + aq.markerOptions, + ); + } + } + } + } + ax.restore(); + }; + L.jqplot.LineRenderer.prototype.drawShadow = function (ah, aj, ai) {}; + function z(ak, aj, ah) { + for (var ai = 0; ai < this.series.length; ai++) { + if (this.series[ai].renderer.constructor == L.jqplot.LineRenderer) { + if (this.series[ai].highlightMouseOver) { + this.series[ai].highlightMouseDown = false; + } + } + } + } + function af() { + if ( + this.plugins.lineRenderer && + this.plugins.lineRenderer.highlightCanvas + ) { + this.plugins.lineRenderer.highlightCanvas.resetCanvas(); + this.plugins.lineRenderer.highlightCanvas = null; + } + this.plugins.lineRenderer.highlightedSeriesIndex = null; + this.plugins.lineRenderer.highlightCanvas = + new L.jqplot.GenericCanvas(); + this.eventCanvas._elem.before( + this.plugins.lineRenderer.highlightCanvas.createElement( + this._gridPadding, + "jqplot-lineRenderer-highlight-canvas", + this._plotDimensions, + this, + ), + ); + this.plugins.lineRenderer.highlightCanvas.setContext(); + this.eventCanvas._elem.bind( + "mouseleave", + { plot: this }, + function (ah) { + aa(ah.data.plot); + }, + ); + } + function ac(an, am, ak, aj) { + var ai = an.series[am]; + var ah = an.plugins.lineRenderer.highlightCanvas; + ah._ctx.clearRect(0, 0, ah._ctx.canvas.width, ah._ctx.canvas.height); + ai._highlightedPoint = ak; + an.plugins.lineRenderer.highlightedSeriesIndex = am; + var al = { fillStyle: ai.highlightColor }; + if (ai.type === "line" && ai.renderer.bands.show) { + al.fill = true; + al.closePath = true; + } + ai.renderer.shapeRenderer.draw(ah._ctx, aj, al); + ah = null; + } + function aa(aj) { + var ah = aj.plugins.lineRenderer.highlightCanvas; + ah._ctx.clearRect(0, 0, ah._ctx.canvas.width, ah._ctx.canvas.height); + for (var ai = 0; ai < aj.series.length; ai++) { + aj.series[ai]._highlightedPoint = null; + } + aj.plugins.lineRenderer.highlightedSeriesIndex = null; + aj.target.trigger("jqplotDataUnhighlight"); + ah = null; + } + function h(al, ak, ao, an, am) { + if (an) { + var aj = [an.seriesIndex, an.pointIndex, an.data]; + var ai = jQuery.Event("jqplotDataMouseOver"); + ai.pageX = al.pageX; + ai.pageY = al.pageY; + am.target.trigger(ai, aj); + if ( + am.series[aj[0]].highlightMouseOver && + !(aj[0] == am.plugins.lineRenderer.highlightedSeriesIndex) + ) { + var ah = jQuery.Event("jqplotDataHighlight"); + ah.which = al.which; + ah.pageX = al.pageX; + ah.pageY = al.pageY; + am.target.trigger(ah, aj); + ac(am, an.seriesIndex, an.pointIndex, an.points); + } + } else { + if (an == null) { + aa(am); + } + } + } + function e(ak, aj, an, am, al) { + if (am) { + var ai = [am.seriesIndex, am.pointIndex, am.data]; + if ( + al.series[ai[0]].highlightMouseDown && + !(ai[0] == al.plugins.lineRenderer.highlightedSeriesIndex) + ) { + var ah = jQuery.Event("jqplotDataHighlight"); + ah.which = ak.which; + ah.pageX = ak.pageX; + ah.pageY = ak.pageY; + al.target.trigger(ah, ai); + ac(al, am.seriesIndex, am.pointIndex, am.points); + } + } else { + if (am == null) { + aa(al); + } + } + } + function ad(aj, ai, am, al, ak) { + var ah = ak.plugins.lineRenderer.highlightedSeriesIndex; + if (ah != null && ak.series[ah].highlightMouseDown) { + aa(ak); + } + } + function g(ak, aj, an, am, al) { + if (am) { + var ai = [am.seriesIndex, am.pointIndex, am.data]; + var ah = jQuery.Event("jqplotDataClick"); + ah.which = ak.which; + ah.pageX = ak.pageX; + ah.pageY = ak.pageY; + al.target.trigger(ah, ai); + } + } + function s(al, ak, ao, an, am) { + if (an) { + var aj = [an.seriesIndex, an.pointIndex, an.data]; + var ah = am.plugins.lineRenderer.highlightedSeriesIndex; + if (ah != null && am.series[ah].highlightMouseDown) { + aa(am); + } + var ai = jQuery.Event("jqplotDataRightClick"); + ai.which = al.which; + ai.pageX = al.pageX; + ai.pageY = al.pageY; + am.target.trigger(ai, aj); + } + } + L.jqplot.LinearAxisRenderer = function () {}; + L.jqplot.LinearAxisRenderer.prototype.init = function (ah) { + this.breakPoints = null; + this.breakTickLabel = "≈"; + this.drawBaseline = true; + this.baselineWidth = null; + this.baselineColor = null; + this.forceTickAt0 = false; + this.forceTickAt100 = false; + this.tickInset = 0; + this.minorTicks = 0; + this.alignTicks = false; + this._autoFormatString = ""; + this._overrideFormatString = false; + this._scalefact = 1; + L.extend(true, this, ah); + if (this.breakPoints) { + if (!L.isArray(this.breakPoints)) { + this.breakPoints = null; + } else { + if ( + this.breakPoints.length < 2 || + this.breakPoints[1] <= this.breakPoints[0] + ) { + this.breakPoints = null; + } + } + } + if (this.numberTicks != null && this.numberTicks < 2) { + this.numberTicks = 2; + } + this.resetDataBounds(); + }; + L.jqplot.LinearAxisRenderer.prototype.draw = function (ah, ao) { + if (this.show) { + this.renderer.createTicks.call(this, ao); + var an = 0; + var ai; + if (this._elem) { + this._elem.emptyForce(); + this._elem = null; + } + this._elem = L(document.createElement("div")); + this._elem.addClass("jqplot-axis jqplot-" + this.name); + this._elem.css("position", "absolute"); + if (this.name == "xaxis" || this.name == "x2axis") { + this._elem.width(this._plotDimensions.width); + } else { + this._elem.height(this._plotDimensions.height); + } + this.labelOptions.axis = this.name; + this._label = new this.labelRenderer(this.labelOptions); + if (this._label.show) { + var am = this._label.draw(ah, ao); + am.appendTo(this._elem); + am = null; + } + var al = this._ticks; + var ak; + for (var aj = 0; aj < al.length; aj++) { + ak = al[aj]; + if ( + ak.show && + ak.showLabel && + (!ak.isMinorTick || this.showMinorTicks) + ) { + this._elem.append(ak.draw(ah, ao)); + } + } + ak = null; + al = null; + } + return this._elem; + }; + L.jqplot.LinearAxisRenderer.prototype.reset = function () { + this.min = this._options.min; + this.max = this._options.max; + this.tickInterval = this._options.tickInterval; + this.numberTicks = this._options.numberTicks; + this._autoFormatString = ""; + if ( + this._overrideFormatString && + this.tickOptions && + this.tickOptions.formatString + ) { + this.tickOptions.formatString = ""; + } + }; + L.jqplot.LinearAxisRenderer.prototype.set = function () { + var ao = 0; + var aj; + var ai = 0; + var an = 0; + var ah = this._label == null ? false : this._label.show; + if (this.show) { + var am = this._ticks; + var al; + for (var ak = 0; ak < am.length; ak++) { + al = am[ak]; + if ( + !al._breakTick && + al.show && + al.showLabel && + (!al.isMinorTick || this.showMinorTicks) + ) { + if (this.name == "xaxis" || this.name == "x2axis") { + aj = al._elem.outerHeight(true); + } else { + aj = al._elem.outerWidth(true); + } + if (aj > ao) { + ao = aj; + } + } + } + al = null; + am = null; + if (ah) { + ai = this._label._elem.outerWidth(true); + an = this._label._elem.outerHeight(true); + } + if (this.name == "xaxis") { + ao = ao + an; + this._elem.css({ + height: ao + "px", + left: "0px", + bottom: "0px", + }); + } else { + if (this.name == "x2axis") { + ao = ao + an; + this._elem.css({ + height: ao + "px", + left: "0px", + top: "0px", + }); + } else { + if (this.name == "yaxis") { + ao = ao + ai; + this._elem.css({ + width: ao + "px", + left: "0px", + top: "0px", + }); + if ( + ah && + this._label.constructor == + L.jqplot.AxisLabelRenderer + ) { + this._label._elem.css("width", ai + "px"); + } + } else { + ao = ao + ai; + this._elem.css({ + width: ao + "px", + right: "0px", + top: "0px", + }); + if ( + ah && + this._label.constructor == + L.jqplot.AxisLabelRenderer + ) { + this._label._elem.css("width", ai + "px"); + } + } + } + } + } + }; + L.jqplot.LinearAxisRenderer.prototype.createTicks = function (aj) { + var aT = this._ticks; + var aK = this.ticks; + var az = this.name; + var aB = this._dataBounds; + var ah = + this.name.charAt(0) === "x" + ? this._plotDimensions.width + : this._plotDimensions.height; + var an; + var a6, aI; + var ap, ao; + var a4, a0; + var aH = this.min; + var a5 = this.max; + var aW = this.numberTicks; + var ba = this.tickInterval; + var am = 30; + this._scalefact = (Math.max(ah, am + 1) - am) / 300; + if (aK.length) { + for (a0 = 0; a0 < aK.length; a0++) { + var aO = aK[a0]; + var aU = new this.tickRenderer(this.tickOptions); + if (L.isArray(aO)) { + aU.value = aO[0]; + if (this.breakPoints) { + if (aO[0] == this.breakPoints[0]) { + aU.label = this.breakTickLabel; + aU._breakTick = true; + aU.showGridline = false; + aU.showMark = false; + } else { + if ( + aO[0] > this.breakPoints[0] && + aO[0] <= this.breakPoints[1] + ) { + aU.show = false; + aU.showGridline = false; + aU.label = aO[1]; + } else { + aU.label = aO[1]; + } + } + } else { + aU.label = aO[1]; + } + aU.setTick(aO[0], this.name); + this._ticks.push(aU); + } else { + if (L.isPlainObject(aO)) { + L.extend(true, aU, aO); + aU.axis = this.name; + this._ticks.push(aU); + } else { + aU.value = aO; + if (this.breakPoints) { + if (aO == this.breakPoints[0]) { + aU.label = this.breakTickLabel; + aU._breakTick = true; + aU.showGridline = false; + aU.showMark = false; + } else { + if ( + aO > this.breakPoints[0] && + aO <= this.breakPoints[1] + ) { + aU.show = false; + aU.showGridline = false; + } + } + } + aU.setTick(aO, this.name); + this._ticks.push(aU); + } + } + } + this.numberTicks = aK.length; + this.min = this._ticks[0].value; + this.max = this._ticks[this.numberTicks - 1].value; + this.tickInterval = (this.max - this.min) / (this.numberTicks - 1); + } else { + if (az == "xaxis" || az == "x2axis") { + ah = this._plotDimensions.width; + } else { + ah = this._plotDimensions.height; + } + var ax = this.numberTicks; + if (this.alignTicks) { + if (this.name === "x2axis" && aj.axes.xaxis.show) { + ax = aj.axes.xaxis.numberTicks; + } else { + if ( + this.name.charAt(0) === "y" && + this.name !== "yaxis" && + this.name !== "yMidAxis" && + aj.axes.yaxis.show + ) { + ax = aj.axes.yaxis.numberTicks; + } + } + } + a6 = this.min != null ? this.min : aB.min; + aI = this.max != null ? this.max : aB.max; + var av = aI - a6; + var aS, ay; + var at; + if (this.tickOptions == null || !this.tickOptions.formatString) { + this._overrideFormatString = true; + } + if ( + this.min == null || + (this.max == null && + this.tickInterval == null && + !this.autoscale) + ) { + if (this.forceTickAt0) { + if (a6 > 0) { + a6 = 0; + } + if (aI < 0) { + aI = 0; + } + } + if (this.forceTickAt100) { + if (a6 > 100) { + a6 = 100; + } + if (aI < 100) { + aI = 100; + } + } + var aE = false, + a1 = false; + if (this.min != null) { + aE = true; + } else { + if (this.max != null) { + a1 = true; + } + } + var aP = L.jqplot.LinearTickGenerator( + a6, + aI, + this._scalefact, + ax, + aE, + a1, + ); + var aw = this.min != null ? a6 : a6 + av * (this.padMin - 1); + var aQ = this.max != null ? aI : aI - av * (this.padMax - 1); + if (a6 < aw || aI > aQ) { + aw = this.min != null ? a6 : a6 - av * (this.padMin - 1); + aQ = this.max != null ? aI : aI + av * (this.padMax - 1); + aP = L.jqplot.LinearTickGenerator( + aw, + aQ, + this._scalefact, + ax, + aE, + a1, + ); + } + this.min = aP[0]; + this.max = aP[1]; + this.numberTicks = aP[2]; + this._autoFormatString = aP[3]; + this.tickInterval = aP[4]; + } else { + if (a6 == aI) { + var ai = 0.05; + if (a6 > 0) { + ai = Math.max(Math.log(a6) / Math.LN10, 0.05); + } + a6 -= ai; + aI += ai; + } + if (this.autoscale && this.min == null && this.max == null) { + var ak, al, ar; + var aC = false; + var aN = false; + var aA = { + min: null, + max: null, + average: null, + stddev: null, + }; + for (var a0 = 0; a0 < this._series.length; a0++) { + var aV = this._series[a0]; + var aD = + aV.fillAxis == "x" + ? aV._xaxis.name + : aV._yaxis.name; + if (this.name == aD) { + var aR = aV._plotValues[aV.fillAxis]; + var aG = aR[0]; + var a2 = aR[0]; + for (var aZ = 1; aZ < aR.length; aZ++) { + if (aR[aZ] < aG) { + aG = aR[aZ]; + } else { + if (aR[aZ] > a2) { + a2 = aR[aZ]; + } + } + } + var au = (a2 - aG) / a2; + if ( + aV.renderer.constructor == L.jqplot.BarRenderer + ) { + if (aG >= 0 && (aV.fillToZero || au > 0.1)) { + aC = true; + } else { + aC = false; + if ( + aV.fill && + aV.fillToZero && + aG < 0 && + a2 > 0 + ) { + aN = true; + } else { + aN = false; + } + } + } else { + if (aV.fill) { + if ( + aG >= 0 && + (aV.fillToZero || au > 0.1) + ) { + aC = true; + } else { + if (aG < 0 && a2 > 0 && aV.fillToZero) { + aC = false; + aN = true; + } else { + aC = false; + aN = false; + } + } + } else { + if (aG < 0) { + aC = false; + } + } + } + } + } + if (aC) { + this.numberTicks = + 2 + + Math.ceil( + (ah - (this.tickSpacing - 1)) / + this.tickSpacing, + ); + this.min = 0; + aH = 0; + al = aI / (this.numberTicks - 1); + at = Math.pow( + 10, + Math.abs(Math.floor(Math.log(al) / Math.LN10)), + ); + if (al / at == parseInt(al / at, 10)) { + al += at; + } + this.tickInterval = Math.ceil(al / at) * at; + this.max = this.tickInterval * (this.numberTicks - 1); + } else { + if (aN) { + this.numberTicks = + 2 + + Math.ceil( + (ah - (this.tickSpacing - 1)) / + this.tickSpacing, + ); + var aJ = Math.ceil( + (Math.abs(a6) / av) * (this.numberTicks - 1), + ); + var a9 = this.numberTicks - 1 - aJ; + al = Math.max(Math.abs(a6 / aJ), Math.abs(aI / a9)); + at = Math.pow( + 10, + Math.abs(Math.floor(Math.log(al) / Math.LN10)), + ); + this.tickInterval = Math.ceil(al / at) * at; + this.max = this.tickInterval * a9; + this.min = -this.tickInterval * aJ; + } else { + if (this.numberTicks == null) { + if (this.tickInterval) { + this.numberTicks = + 3 + Math.ceil(av / this.tickInterval); + } else { + this.numberTicks = + 2 + + Math.ceil( + (ah - (this.tickSpacing - 1)) / + this.tickSpacing, + ); + } + } + if (this.tickInterval == null) { + al = av / (this.numberTicks - 1); + if (al < 1) { + at = Math.pow( + 10, + Math.abs( + Math.floor( + Math.log(al) / Math.LN10, + ), + ), + ); + } else { + at = 1; + } + this.tickInterval = + Math.ceil(al * at * this.pad) / at; + } else { + at = 1 / this.tickInterval; + } + ak = this.tickInterval * (this.numberTicks - 1); + ar = (ak - av) / 2; + if (this.min == null) { + this.min = Math.floor(at * (a6 - ar)) / at; + } + if (this.max == null) { + this.max = this.min + ak; + } + } + } + var aF = L.jqplot.getSignificantFigures(this.tickInterval); + var aM; + if (aF.digitsLeft >= aF.significantDigits) { + aM = "%d"; + } else { + var at = Math.max(0, 5 - aF.digitsLeft); + at = Math.min(at, aF.digitsRight); + aM = "%." + at + "f"; + } + this._autoFormatString = aM; + } else { + aS = + this.min != null + ? this.min + : a6 - av * (this.padMin - 1); + ay = + this.max != null + ? this.max + : aI + av * (this.padMax - 1); + av = ay - aS; + if (this.numberTicks == null) { + if (this.tickInterval != null) { + this.numberTicks = + Math.ceil((ay - aS) / this.tickInterval) + 1; + } else { + if (ah > 100) { + this.numberTicks = parseInt( + 3 + (ah - 100) / 75, + 10, + ); + } else { + this.numberTicks = 2; + } + } + } + if (this.tickInterval == null) { + this.tickInterval = av / (this.numberTicks - 1); + } + if (this.max == null) { + ay = aS + this.tickInterval * (this.numberTicks - 1); + } + if (this.min == null) { + aS = ay - this.tickInterval * (this.numberTicks - 1); + } + var aF = L.jqplot.getSignificantFigures(this.tickInterval); + var aM; + if (aF.digitsLeft >= aF.significantDigits) { + aM = "%d"; + } else { + var at = Math.max(0, 5 - aF.digitsLeft); + at = Math.min(at, aF.digitsRight); + aM = "%." + at + "f"; + } + this._autoFormatString = aM; + this.min = aS; + this.max = ay; + } + if ( + this.renderer.constructor == L.jqplot.LinearAxisRenderer && + this._autoFormatString == "" + ) { + av = this.max - this.min; + var a7 = new this.tickRenderer(this.tickOptions); + var aL = + a7.formatString || + L.jqplot.config.defaultTickFormatString; + var aL = aL.match(L.jqplot.sprintf.regex)[0]; + var a3 = 0; + if (aL) { + if (aL.search(/[fFeEgGpP]/) > -1) { + var aY = aL.match(/\%\.(\d{0,})?[eEfFgGpP]/); + if (aY) { + a3 = parseInt(aY[1], 10); + } else { + a3 = 6; + } + } else { + if (aL.search(/[di]/) > -1) { + a3 = 0; + } + } + var aq = Math.pow(10, -a3); + if (this.tickInterval < aq) { + if (aW == null && ba == null) { + this.tickInterval = aq; + if (a5 == null && aH == null) { + this.min = + Math.floor(this._dataBounds.min / aq) * + aq; + if (this.min == this._dataBounds.min) { + this.min = + this._dataBounds.min - + this.tickInterval; + } + this.max = + Math.ceil(this._dataBounds.max / aq) * + aq; + if (this.max == this._dataBounds.max) { + this.max = + this._dataBounds.max + + this.tickInterval; + } + var aX = + (this.max - this.min) / + this.tickInterval; + aX = aX.toFixed(11); + aX = Math.ceil(aX); + this.numberTicks = aX + 1; + } else { + if (a5 == null) { + var aX = + (this._dataBounds.max - this.min) / + this.tickInterval; + aX = aX.toFixed(11); + this.numberTicks = Math.ceil(aX) + 2; + this.max = + this.min + + this.tickInterval * + (this.numberTicks - 1); + } else { + if (aH == null) { + var aX = + (this.max - + this._dataBounds.min) / + this.tickInterval; + aX = aX.toFixed(11); + this.numberTicks = + Math.ceil(aX) + 2; + this.min = + this.max - + this.tickInterval * + (this.numberTicks - 1); + } else { + this.numberTicks = + Math.ceil( + (a5 - aH) / + this.tickInterval, + ) + 1; + this.min = + Math.floor( + aH * Math.pow(10, a3), + ) / Math.pow(10, a3); + this.max = + Math.ceil( + a5 * Math.pow(10, a3), + ) / Math.pow(10, a3); + this.numberTicks = + Math.ceil( + (this.max - this.min) / + this.tickInterval, + ) + 1; + } + } + } + } + } + } + } + } + if (this._overrideFormatString && this._autoFormatString != "") { + this.tickOptions = this.tickOptions || {}; + this.tickOptions.formatString = this._autoFormatString; + } + var aU, a8; + for (var a0 = 0; a0 < this.numberTicks; a0++) { + a4 = this.min + a0 * this.tickInterval; + aU = new this.tickRenderer(this.tickOptions); + aU.setTick(a4, this.name); + this._ticks.push(aU); + if (a0 < this.numberTicks - 1) { + for (var aZ = 0; aZ < this.minorTicks; aZ++) { + a4 += this.tickInterval / (this.minorTicks + 1); + a8 = L.extend(true, {}, this.tickOptions, { + name: this.name, + value: a4, + label: "", + isMinorTick: true, + }); + aU = new this.tickRenderer(a8); + this._ticks.push(aU); + } + } + aU = null; + } + } + if (this.tickInset) { + this.min = this.min - this.tickInset * this.tickInterval; + this.max = this.max + this.tickInset * this.tickInterval; + } + aT = null; + }; + L.jqplot.LinearAxisRenderer.prototype.resetTickValues = function (aj) { + if (L.isArray(aj) && aj.length == this._ticks.length) { + var ai; + for (var ah = 0; ah < aj.length; ah++) { + ai = this._ticks[ah]; + ai.value = aj[ah]; + ai.label = ai.formatter(ai.formatString, aj[ah]); + ai.label = ai.prefix + ai.label; + ai._elem.html(ai.label); + } + ai = null; + this.min = L.jqplot.arrayMin(aj); + this.max = L.jqplot.arrayMax(aj); + this.pack(); + } + }; + L.jqplot.LinearAxisRenderer.prototype.pack = function (aj, ai) { + aj = aj || {}; + ai = ai || this._offsets; + var ay = this._ticks; + var au = this.max; + var at = this.min; + var ao = ai.max; + var am = ai.min; + var aq = this._label == null ? false : this._label.show; + for (var ar in aj) { + this._elem.css(ar, aj[ar]); + } + this._offsets = ai; + var ak = ao - am; + var al = au - at; + if (this.breakPoints) { + al = al - this.breakPoints[1] + this.breakPoints[0]; + this.p2u = function (aA) { + return ((aA - am) * al) / ak + at; + }; + this.u2p = function (aA) { + if (aA > this.breakPoints[0] && aA < this.breakPoints[1]) { + aA = this.breakPoints[0]; + } + if (aA <= this.breakPoints[0]) { + return ((aA - at) * ak) / al + am; + } else { + return ( + ((aA - this.breakPoints[1] + this.breakPoints[0] - at) * + ak) / + al + + am + ); + } + }; + if (this.name.charAt(0) == "x") { + this.series_u2p = function (aA) { + if (aA > this.breakPoints[0] && aA < this.breakPoints[1]) { + aA = this.breakPoints[0]; + } + if (aA <= this.breakPoints[0]) { + return ((aA - at) * ak) / al; + } else { + return ( + ((aA - + this.breakPoints[1] + + this.breakPoints[0] - + at) * + ak) / + al + ); + } + }; + this.series_p2u = function (aA) { + return (aA * al) / ak + at; + }; + } else { + this.series_u2p = function (aA) { + if (aA > this.breakPoints[0] && aA < this.breakPoints[1]) { + aA = this.breakPoints[0]; + } + if (aA >= this.breakPoints[1]) { + return ((aA - au) * ak) / al; + } else { + return ( + ((aA + + this.breakPoints[1] - + this.breakPoints[0] - + au) * + ak) / + al + ); + } + }; + this.series_p2u = function (aA) { + return (aA * al) / ak + au; + }; + } + } else { + this.p2u = function (aA) { + return ((aA - am) * al) / ak + at; + }; + this.u2p = function (aA) { + return ((aA - at) * ak) / al + am; + }; + if (this.name == "xaxis" || this.name == "x2axis") { + this.series_u2p = function (aA) { + return ((aA - at) * ak) / al; + }; + this.series_p2u = function (aA) { + return (aA * al) / ak + at; + }; + } else { + this.series_u2p = function (aA) { + return ((aA - au) * ak) / al; + }; + this.series_p2u = function (aA) { + return (aA * al) / ak + au; + }; + } + } + if (this.show) { + if (this.name == "xaxis" || this.name == "x2axis") { + for (var av = 0; av < ay.length; av++) { + var ap = ay[av]; + if (ap.show && ap.showLabel) { + var ah; + if ( + ap.constructor == L.jqplot.CanvasAxisTickRenderer && + ap.angle + ) { + var ax = this.name == "xaxis" ? 1 : -1; + switch (ap.labelPosition) { + case "auto": + if (ax * ap.angle < 0) { + ah = + -ap.getWidth() + + (ap._textRenderer.height * + Math.sin( + -ap._textRenderer.angle, + )) / + 2; + } else { + ah = + (-ap._textRenderer.height * + Math.sin( + ap._textRenderer.angle, + )) / + 2; + } + break; + case "end": + ah = + -ap.getWidth() + + (ap._textRenderer.height * + Math.sin(-ap._textRenderer.angle)) / + 2; + break; + case "start": + ah = + (-ap._textRenderer.height * + Math.sin(ap._textRenderer.angle)) / + 2; + break; + case "middle": + ah = + -ap.getWidth() / 2 + + (ap._textRenderer.height * + Math.sin(-ap._textRenderer.angle)) / + 2; + break; + default: + ah = + -ap.getWidth() / 2 + + (ap._textRenderer.height * + Math.sin(-ap._textRenderer.angle)) / + 2; + break; + } + } else { + ah = -ap.getWidth() / 2; + } + var az = this.u2p(ap.value) + ah + "px"; + ap._elem.css("left", az); + ap.pack(); + } + } + if (aq) { + var an = this._label._elem.outerWidth(true); + this._label._elem.css("left", am + ak / 2 - an / 2 + "px"); + if (this.name == "xaxis") { + this._label._elem.css("bottom", "0px"); + } else { + this._label._elem.css("top", "0px"); + } + this._label.pack(); + } + } else { + for (var av = 0; av < ay.length; av++) { + var ap = ay[av]; + if (ap.show && ap.showLabel) { + var ah; + if ( + ap.constructor == L.jqplot.CanvasAxisTickRenderer && + ap.angle + ) { + var ax = this.name == "yaxis" ? 1 : -1; + switch (ap.labelPosition) { + case "auto": + case "end": + if (ax * ap.angle < 0) { + ah = + (-ap._textRenderer.height * + Math.cos( + -ap._textRenderer.angle, + )) / + 2; + } else { + ah = + -ap.getHeight() + + (ap._textRenderer.height * + Math.cos( + ap._textRenderer.angle, + )) / + 2; + } + break; + case "start": + if (ap.angle > 0) { + ah = + (-ap._textRenderer.height * + Math.cos( + -ap._textRenderer.angle, + )) / + 2; + } else { + ah = + -ap.getHeight() + + (ap._textRenderer.height * + Math.cos( + ap._textRenderer.angle, + )) / + 2; + } + break; + case "middle": + ah = -ap.getHeight() / 2; + break; + default: + ah = -ap.getHeight() / 2; + break; + } + } else { + ah = -ap.getHeight() / 2; + } + var az = this.u2p(ap.value) + ah + "px"; + ap._elem.css("top", az); + ap.pack(); + } + } + if (aq) { + var aw = this._label._elem.outerHeight(true); + this._label._elem.css("top", ao - ak / 2 - aw / 2 + "px"); + if (this.name == "yaxis") { + this._label._elem.css("left", "0px"); + } else { + this._label._elem.css("right", "0px"); + } + this._label.pack(); + } + } + } + ay = null; + }; + function i(ai) { + var ah; + ai = Math.abs(ai); + if (ai >= 10) { + ah = "%d"; + } else { + if (ai > 1) { + if (ai === parseInt(ai, 10)) { + ah = "%d"; + } else { + ah = "%.1f"; + } + } else { + var aj = -Math.floor(Math.log(ai) / Math.LN10); + ah = "%." + aj + "f"; + } + } + return ah; + } + var b = [0.1, 0.2, 0.3, 0.4, 0.5, 0.8, 1, 2, 3, 4, 5]; + var c = function (ai) { + var ah = b.indexOf(ai); + if (ah > 0) { + return b[ah - 1]; + } else { + return b[b.length - 1] / 100; + } + }; + var k = function (ai) { + var ah = b.indexOf(ai); + if (ah < b.length - 1) { + return b[ah + 1]; + } else { + return b[0] * 100; + } + }; + function d(al, au, at) { + var aq = Math.floor(at / 2); + var ai = Math.ceil(at * 1.5); + var ak = Number.MAX_VALUE; + var ah = au - al; + var ax; + var ap; + var ar; + var ay = L.jqplot.getSignificantFigures; + var aw; + var an; + var ao; + var av; + for (var am = 0, aj = ai - aq + 1; am < aj; am++) { + ao = aq + am; + ax = ah / (ao - 1); + ap = ay(ax); + ax = Math.abs(at - ao) + ap.digitsRight; + if (ax < ak) { + ak = ax; + ar = ao; + av = ap.digitsRight; + } else { + if (ax === ak) { + if (ap.digitsRight < av) { + ar = ao; + av = ap.digitsRight; + } + } + } + } + aw = Math.max(av, Math.max(ay(al).digitsRight, ay(au).digitsRight)); + if (aw === 0) { + an = "%d"; + } else { + an = "%." + aw + "f"; + } + ax = ah / (ar - 1); + return [al, au, ar, an, ax]; + } + function W(ai, al) { + al = al || 7; + var ak = ai / (al - 1); + var aj = Math.pow(10, Math.floor(Math.log(ak) / Math.LN10)); + var am = ak / aj; + var ah; + if (aj < 1) { + if (am > 5) { + ah = 10 * aj; + } else { + if (am > 2) { + ah = 5 * aj; + } else { + if (am > 1) { + ah = 2 * aj; + } else { + ah = aj; + } + } + } + } else { + if (am > 5) { + ah = 10 * aj; + } else { + if (am > 4) { + ah = 5 * aj; + } else { + if (am > 3) { + ah = 4 * aj; + } else { + if (am > 2) { + ah = 3 * aj; + } else { + if (am > 1) { + ah = 2 * aj; + } else { + ah = aj; + } + } + } + } + } + } + return ah; + } + function Q(ai, ah) { + ah = ah || 1; + var ak = Math.floor(Math.log(ai) / Math.LN10); + var am = Math.pow(10, ak); + var al = ai / am; + var aj; + al = al / ah; + if (al <= 0.38) { + aj = 0.1; + } else { + if (al <= 1.6) { + aj = 0.2; + } else { + if (al <= 4) { + aj = 0.5; + } else { + if (al <= 8) { + aj = 1; + } else { + if (al <= 16) { + aj = 2; + } else { + aj = 5; + } + } + } + } + } + return aj * am; + } + function x(aj, ai) { + var al = Math.floor(Math.log(aj) / Math.LN10); + var an = Math.pow(10, al); + var am = aj / an; + var ah; + var ak; + am = am / ai; + if (am <= 0.38) { + ak = 0.1; + } else { + if (am <= 1.6) { + ak = 0.2; + } else { + if (am <= 4) { + ak = 0.5; + } else { + if (am <= 8) { + ak = 1; + } else { + if (am <= 16) { + ak = 2; + } else { + ak = 5; + } + } + } + } + } + ah = ak * an; + return [ah, ak, an]; + } + L.jqplot.LinearTickGenerator = function (an, aq, aj, ak, ao, ar) { + ao = ao === null ? false : ao; + ar = ar === null || ao ? false : ar; + if (an === aq) { + aq = aq ? 0 : 1; + } + aj = aj || 1; + if (aq < an) { + var at = aq; + aq = an; + an = at; + } + var ai = []; + var aw = Q(aq - an, aj); + var av = L.jqplot.getSignificantFigures; + if (ak == null) { + if (!ao && !ar) { + ai[0] = Math.floor(an / aw) * aw; + ai[1] = Math.ceil(aq / aw) * aw; + ai[2] = Math.round((ai[1] - ai[0]) / aw + 1); + ai[3] = i(aw); + ai[4] = aw; + } else { + if (ao) { + ai[0] = an; + ai[2] = Math.ceil((aq - an) / aw + 1); + ai[1] = an + (ai[2] - 1) * aw; + var au = av(an).digitsRight; + var ap = av(aw).digitsRight; + if (au < ap) { + ai[3] = i(aw); + } else { + ai[3] = "%." + au + "f"; + } + ai[4] = aw; + } else { + if (ar) { + ai[1] = aq; + ai[2] = Math.ceil((aq - an) / aw + 1); + ai[0] = aq - (ai[2] - 1) * aw; + var al = av(aq).digitsRight; + var ap = av(aw).digitsRight; + if (al < ap) { + ai[3] = i(aw); + } else { + ai[3] = "%." + al + "f"; + } + ai[4] = aw; + } + } + } + } else { + var am = []; + am[0] = Math.floor(an / aw) * aw; + am[1] = Math.ceil(aq / aw) * aw; + am[2] = Math.round((am[1] - am[0]) / aw + 1); + am[3] = i(aw); + am[4] = aw; + if (am[2] === ak) { + ai = am; + } else { + var ah = W(am[1] - am[0], ak); + ai[0] = am[0]; + ai[2] = ak; + ai[4] = ah; + ai[3] = i(ah); + ai[1] = ai[0] + (ai[2] - 1) * ai[4]; + } + } + return ai; + }; + L.jqplot.LinearTickGenerator.bestLinearInterval = Q; + L.jqplot.LinearTickGenerator.bestInterval = W; + L.jqplot.LinearTickGenerator.bestLinearComponents = x; + L.jqplot.LinearTickGenerator.bestConstrainedInterval = d; + L.jqplot.MarkerRenderer = function (ah) { + this.show = true; + this.style = "filledCircle"; + this.lineWidth = 2; + this.size = 9; + this.color = "#666666"; + this.shadow = true; + this.shadowAngle = 45; + this.shadowOffset = 1; + this.shadowDepth = 3; + this.shadowAlpha = "0.07"; + this.shadowRenderer = new L.jqplot.ShadowRenderer(); + this.shapeRenderer = new L.jqplot.ShapeRenderer(); + L.extend(true, this, ah); + }; + L.jqplot.MarkerRenderer.prototype.init = function (ah) { + L.extend(true, this, ah); + var aj = { + angle: this.shadowAngle, + offset: this.shadowOffset, + alpha: this.shadowAlpha, + lineWidth: this.lineWidth, + depth: this.shadowDepth, + closePath: true, + }; + if (this.style.indexOf("filled") != -1) { + aj.fill = true; + } + if (this.style.indexOf("ircle") != -1) { + aj.isarc = true; + aj.closePath = false; + } + this.shadowRenderer.init(aj); + var ai = { + fill: false, + isarc: false, + strokeStyle: this.color, + fillStyle: this.color, + lineWidth: this.lineWidth, + closePath: true, + }; + if (this.style.indexOf("filled") != -1) { + ai.fill = true; + } + if (this.style.indexOf("ircle") != -1) { + ai.isarc = true; + ai.closePath = false; + } + this.shapeRenderer.init(ai); + }; + L.jqplot.MarkerRenderer.prototype.drawDiamond = function ( + aj, + ai, + am, + al, + ao, + ) { + var ah = 1.2; + var ap = this.size / 2 / ah; + var an = (this.size / 2) * ah; + var ak = [ + [aj - ap, ai], + [aj, ai + an], + [aj + ap, ai], + [aj, ai - an], + ]; + if (this.shadow) { + this.shadowRenderer.draw(am, ak); + } + this.shapeRenderer.draw(am, ak, ao); + }; + L.jqplot.MarkerRenderer.prototype.drawPlus = function (ak, aj, an, am, aq) { + var ai = 1; + var ar = (this.size / 2) * ai; + var ao = (this.size / 2) * ai; + var ap = [ + [ak, aj - ao], + [ak, aj + ao], + ]; + var al = [ + [ak + ar, aj], + [ak - ar, aj], + ]; + var ah = L.extend(true, {}, this.options, { closePath: false }); + if (this.shadow) { + this.shadowRenderer.draw(an, ap, { closePath: false }); + this.shadowRenderer.draw(an, al, { closePath: false }); + } + this.shapeRenderer.draw(an, ap, ah); + this.shapeRenderer.draw(an, al, ah); + }; + L.jqplot.MarkerRenderer.prototype.drawX = function (ak, aj, an, am, aq) { + var ai = 1; + var ar = (this.size / 2) * ai; + var ao = (this.size / 2) * ai; + var ah = L.extend(true, {}, this.options, { closePath: false }); + var ap = [ + [ak - ar, aj - ao], + [ak + ar, aj + ao], + ]; + var al = [ + [ak - ar, aj + ao], + [ak + ar, aj - ao], + ]; + if (this.shadow) { + this.shadowRenderer.draw(an, ap, { closePath: false }); + this.shadowRenderer.draw(an, al, { closePath: false }); + } + this.shapeRenderer.draw(an, ap, ah); + this.shapeRenderer.draw(an, al, ah); + }; + L.jqplot.MarkerRenderer.prototype.drawDash = function (aj, ai, am, al, ao) { + var ah = 1; + var ap = (this.size / 2) * ah; + var an = (this.size / 2) * ah; + var ak = [ + [aj - ap, ai], + [aj + ap, ai], + ]; + if (this.shadow) { + this.shadowRenderer.draw(am, ak); + } + this.shapeRenderer.draw(am, ak, ao); + }; + L.jqplot.MarkerRenderer.prototype.drawLine = function (am, al, ah, ak, ai) { + var aj = [am, al]; + if (this.shadow) { + this.shadowRenderer.draw(ah, aj); + } + this.shapeRenderer.draw(ah, aj, ai); + }; + L.jqplot.MarkerRenderer.prototype.drawSquare = function ( + aj, + ai, + am, + al, + ao, + ) { + var ah = 1; + var ap = this.size / 2 / ah; + var an = (this.size / 2) * ah; + var ak = [ + [aj - ap, ai - an], + [aj - ap, ai + an], + [aj + ap, ai + an], + [aj + ap, ai - an], + ]; + if (this.shadow) { + this.shadowRenderer.draw(am, ak); + } + this.shapeRenderer.draw(am, ak, ao); + }; + L.jqplot.MarkerRenderer.prototype.drawCircle = function ( + ai, + ao, + ak, + an, + al, + ) { + var ah = this.size / 2; + var aj = 2 * Math.PI; + var am = [ai, ao, ah, 0, aj, true]; + if (this.shadow) { + this.shadowRenderer.draw(ak, am); + } + this.shapeRenderer.draw(ak, am, al); + }; + L.jqplot.MarkerRenderer.prototype.draw = function (ah, ak, ai, aj) { + aj = aj || {}; + if (aj.show == null || aj.show != false) { + if (aj.color && !aj.fillStyle) { + aj.fillStyle = aj.color; + } + if (aj.color && !aj.strokeStyle) { + aj.strokeStyle = aj.color; + } + switch (this.style) { + case "diamond": + this.drawDiamond(ah, ak, ai, false, aj); + break; + case "filledDiamond": + this.drawDiamond(ah, ak, ai, true, aj); + break; + case "circle": + this.drawCircle(ah, ak, ai, false, aj); + break; + case "filledCircle": + this.drawCircle(ah, ak, ai, true, aj); + break; + case "square": + this.drawSquare(ah, ak, ai, false, aj); + break; + case "filledSquare": + this.drawSquare(ah, ak, ai, true, aj); + break; + case "x": + this.drawX(ah, ak, ai, true, aj); + break; + case "plus": + this.drawPlus(ah, ak, ai, true, aj); + break; + case "dash": + this.drawDash(ah, ak, ai, true, aj); + break; + case "line": + this.drawLine(ah, ak, ai, false, aj); + break; + default: + this.drawDiamond(ah, ak, ai, false, aj); + break; + } + } + }; + L.jqplot.ShadowRenderer = function (ah) { + this.angle = 45; + this.offset = 1; + this.alpha = 0.07; + this.lineWidth = 1.5; + this.lineJoin = "miter"; + this.lineCap = "round"; + this.closePath = false; + this.fill = false; + this.depth = 3; + this.strokeStyle = "rgba(0,0,0,0.1)"; + this.isarc = false; + L.extend(true, this, ah); + }; + L.jqplot.ShadowRenderer.prototype.init = function (ah) { + L.extend(true, this, ah); + }; + L.jqplot.ShadowRenderer.prototype.draw = function (av, at, ax) { + av.save(); + var ah = ax != null ? ax : {}; + var au = ah.fill != null ? ah.fill : this.fill; + var ap = ah.fillRect != null ? ah.fillRect : this.fillRect; + var ao = ah.closePath != null ? ah.closePath : this.closePath; + var al = ah.offset != null ? ah.offset : this.offset; + var aj = ah.alpha != null ? ah.alpha : this.alpha; + var an = ah.depth != null ? ah.depth : this.depth; + var aw = ah.isarc != null ? ah.isarc : this.isarc; + var aq = ah.linePattern != null ? ah.linePattern : this.linePattern; + av.lineWidth = ah.lineWidth != null ? ah.lineWidth : this.lineWidth; + av.lineJoin = ah.lineJoin != null ? ah.lineJoin : this.lineJoin; + av.lineCap = ah.lineCap != null ? ah.lineCap : this.lineCap; + av.strokeStyle = + ah.strokeStyle || this.strokeStyle || "rgba(0,0,0," + aj + ")"; + av.fillStyle = + ah.fillStyle || this.fillStyle || "rgba(0,0,0," + aj + ")"; + for (var ak = 0; ak < an; ak++) { + var ar = L.jqplot.LinePattern(av, aq); + av.translate( + Math.cos((this.angle * Math.PI) / 180) * al, + Math.sin((this.angle * Math.PI) / 180) * al, + ); + ar.beginPath(); + if (aw) { + av.arc(at[0], at[1], at[2], at[3], at[4], true); + } else { + if (ap) { + if (ap) { + av.fillRect(at[0], at[1], at[2], at[3]); + } + } else { + if (at && at.length) { + var ai = true; + for (var am = 0; am < at.length; am++) { + if (at[am][0] != null && at[am][1] != null) { + if (ai) { + ar.moveTo(at[am][0], at[am][1]); + ai = false; + } else { + ar.lineTo(at[am][0], at[am][1]); + } + } else { + ai = true; + } + } + } + } + } + if (ao) { + ar.closePath(); + } + if (au) { + av.fill(); + } else { + av.stroke(); + } + } + av.restore(); + }; + L.jqplot.ShapeRenderer = function (ah) { + this.lineWidth = 1.5; + this.linePattern = "solid"; + this.lineJoin = "miter"; + this.lineCap = "round"; + this.closePath = false; + this.fill = false; + this.isarc = false; + this.fillRect = false; + this.strokeRect = false; + this.clearRect = false; + this.strokeStyle = "#999999"; + this.fillStyle = "#999999"; + L.extend(true, this, ah); + }; + L.jqplot.ShapeRenderer.prototype.init = function (ah) { + L.extend(true, this, ah); + }; + L.jqplot.ShapeRenderer.prototype.draw = function (at, aq, av) { + at.save(); + var ah = av != null ? av : {}; + var ar = ah.fill != null ? ah.fill : this.fill; + var am = ah.closePath != null ? ah.closePath : this.closePath; + var an = ah.fillRect != null ? ah.fillRect : this.fillRect; + var ak = ah.strokeRect != null ? ah.strokeRect : this.strokeRect; + var ai = ah.clearRect != null ? ah.clearRect : this.clearRect; + var au = ah.isarc != null ? ah.isarc : this.isarc; + var ao = ah.linePattern != null ? ah.linePattern : this.linePattern; + var ap = L.jqplot.LinePattern(at, ao); + at.lineWidth = ah.lineWidth || this.lineWidth; + at.lineJoin = ah.lineJoin || this.lineJoin; + at.lineCap = ah.lineCap || this.lineCap; + at.strokeStyle = ah.strokeStyle || ah.color || this.strokeStyle; + at.fillStyle = ah.fillStyle || this.fillStyle; + at.beginPath(); + if (au) { + at.arc(aq[0], aq[1], aq[2], aq[3], aq[4], true); + if (am) { + at.closePath(); + } + if (ar) { + at.fill(); + } else { + at.stroke(); + } + at.restore(); + return; + } else { + if (ai) { + at.clearRect(aq[0], aq[1], aq[2], aq[3]); + at.restore(); + return; + } else { + if (an || ak) { + if (an) { + at.fillRect(aq[0], aq[1], aq[2], aq[3]); + } + if (ak) { + at.strokeRect(aq[0], aq[1], aq[2], aq[3]); + at.restore(); + return; + } + } else { + if (aq && aq.length) { + var aj = true; + for (var al = 0; al < aq.length; al++) { + if (aq[al][0] != null && aq[al][1] != null) { + if (aj) { + ap.moveTo(aq[al][0], aq[al][1]); + aj = false; + } else { + ap.lineTo(aq[al][0], aq[al][1]); + } + } else { + aj = true; + } + } + if (am) { + ap.closePath(); + } + if (ar) { + at.fill(); + } else { + at.stroke(); + } + } + } + } + } + at.restore(); + }; + L.jqplot.TableLegendRenderer = function () {}; + L.jqplot.TableLegendRenderer.prototype.init = function (ah) { + L.extend(true, this, ah); + }; + L.jqplot.TableLegendRenderer.prototype.addrow = function (aq, ak, ah, ao) { + var al = ah ? this.rowSpacing + "px" : "0px"; + var ap; + var aj; + var ai; + var an; + var am; + ai = document.createElement("tr"); + ap = L(ai); + ap.addClass("jqplot-table-legend"); + ai = null; + if (ao) { + ap.prependTo(this._elem); + } else { + ap.appendTo(this._elem); + } + if (this.showSwatches) { + aj = L(document.createElement("td")); + aj.addClass("jqplot-table-legend jqplot-table-legend-swatch"); + aj.css({ textAlign: "center", paddingTop: al }); + an = L(document.createElement("div")); + an.addClass("jqplot-table-legend-swatch-outline"); + am = L(document.createElement("div")); + am.addClass("jqplot-table-legend-swatch"); + am.css({ backgroundColor: ak, borderColor: ak }); + ap.append(aj.append(an.append(am))); + } + if (this.showLabels) { + aj = L(document.createElement("td")); + aj.addClass("jqplot-table-legend jqplot-table-legend-label"); + aj.css("paddingTop", al); + ap.append(aj); + if (this.escapeHtml) { + aj.text(aq); + } else { + aj.html(aq); + } + } + aj = null; + an = null; + am = null; + ap = null; + ai = null; + }; + L.jqplot.TableLegendRenderer.prototype.draw = function () { + if (this._elem) { + this._elem.emptyForce(); + this._elem = null; + } + if (this.show) { + var am = this._series; + var ai = document.createElement("table"); + this._elem = L(ai); + this._elem.addClass("jqplot-table-legend"); + var ar = { position: "absolute" }; + if (this.background) { + ar.background = this.background; + } + if (this.border) { + ar.border = this.border; + } + if (this.fontSize) { + ar.fontSize = this.fontSize; + } + if (this.fontFamily) { + ar.fontFamily = this.fontFamily; + } + if (this.textColor) { + ar.textColor = this.textColor; + } + if (this.marginTop != null) { + ar.marginTop = this.marginTop; + } + if (this.marginBottom != null) { + ar.marginBottom = this.marginBottom; + } + if (this.marginLeft != null) { + ar.marginLeft = this.marginLeft; + } + if (this.marginRight != null) { + ar.marginRight = this.marginRight; + } + var ah = false, + ao = false, + aq; + for (var an = 0; an < am.length; an++) { + aq = am[an]; + if ( + aq._stack || + aq.renderer.constructor == L.jqplot.BezierCurveRenderer + ) { + ao = true; + } + if (aq.show && aq.showLabel) { + var al = this.labels[an] || aq.label.toString(); + if (al) { + var aj = aq.color; + if (ao && an < am.length - 1) { + ah = true; + } else { + if (ao && an == am.length - 1) { + ah = false; + } + } + this.renderer.addrow.call(this, al, aj, ah, ao); + ah = true; + } + for ( + var ak = 0; + ak < L.jqplot.addLegendRowHooks.length; + ak++ + ) { + var ap = L.jqplot.addLegendRowHooks[ak].call(this, aq); + if (ap) { + this.renderer.addrow.call( + this, + ap.label, + ap.color, + ah, + ); + ah = true; + } + } + al = null; + } + } + } + return this._elem; + }; + L.jqplot.TableLegendRenderer.prototype.pack = function (aj) { + if (this.show) { + if (this.placement == "insideGrid") { + switch (this.location) { + case "nw": + var ai = aj.left; + var ah = aj.top; + this._elem.css("left", ai); + this._elem.css("top", ah); + break; + case "n": + var ai = + (aj.left + + (this._plotDimensions.width - aj.right)) / + 2 - + this.getWidth() / 2; + var ah = aj.top; + this._elem.css("left", ai); + this._elem.css("top", ah); + break; + case "ne": + var ai = aj.right; + var ah = aj.top; + this._elem.css({ right: ai, top: ah }); + break; + case "e": + var ai = aj.right; + var ah = + (aj.top + + (this._plotDimensions.height - aj.bottom)) / + 2 - + this.getHeight() / 2; + this._elem.css({ right: ai, top: ah }); + break; + case "se": + var ai = aj.right; + var ah = aj.bottom; + this._elem.css({ right: ai, bottom: ah }); + break; + case "s": + var ai = + (aj.left + + (this._plotDimensions.width - aj.right)) / + 2 - + this.getWidth() / 2; + var ah = aj.bottom; + this._elem.css({ left: ai, bottom: ah }); + break; + case "sw": + var ai = aj.left; + var ah = aj.bottom; + this._elem.css({ left: ai, bottom: ah }); + break; + case "w": + var ai = aj.left; + var ah = + (aj.top + + (this._plotDimensions.height - aj.bottom)) / + 2 - + this.getHeight() / 2; + this._elem.css({ left: ai, top: ah }); + break; + default: + var ai = aj.right; + var ah = aj.bottom; + this._elem.css({ right: ai, bottom: ah }); + break; + } + } else { + if (this.placement == "outside") { + switch (this.location) { + case "nw": + var ai = this._plotDimensions.width - aj.left; + var ah = aj.top; + this._elem.css("right", ai); + this._elem.css("top", ah); + break; + case "n": + var ai = + (aj.left + + (this._plotDimensions.width - aj.right)) / + 2 - + this.getWidth() / 2; + var ah = this._plotDimensions.height - aj.top; + this._elem.css("left", ai); + this._elem.css("bottom", ah); + break; + case "ne": + var ai = this._plotDimensions.width - aj.right; + var ah = aj.top; + this._elem.css({ left: ai, top: ah }); + break; + case "e": + var ai = this._plotDimensions.width - aj.right; + var ah = + (aj.top + + (this._plotDimensions.height - aj.bottom)) / + 2 - + this.getHeight() / 2; + this._elem.css({ left: ai, top: ah }); + break; + case "se": + var ai = this._plotDimensions.width - aj.right; + var ah = aj.bottom; + this._elem.css({ left: ai, bottom: ah }); + break; + case "s": + var ai = + (aj.left + + (this._plotDimensions.width - aj.right)) / + 2 - + this.getWidth() / 2; + var ah = this._plotDimensions.height - aj.bottom; + this._elem.css({ left: ai, top: ah }); + break; + case "sw": + var ai = this._plotDimensions.width - aj.left; + var ah = aj.bottom; + this._elem.css({ right: ai, bottom: ah }); + break; + case "w": + var ai = this._plotDimensions.width - aj.left; + var ah = + (aj.top + + (this._plotDimensions.height - aj.bottom)) / + 2 - + this.getHeight() / 2; + this._elem.css({ right: ai, top: ah }); + break; + default: + var ai = aj.right; + var ah = aj.bottom; + this._elem.css({ right: ai, bottom: ah }); + break; + } + } else { + switch (this.location) { + case "nw": + this._elem.css({ left: 0, top: aj.top }); + break; + case "n": + var ai = + (aj.left + + (this._plotDimensions.width - aj.right)) / + 2 - + this.getWidth() / 2; + this._elem.css({ left: ai, top: aj.top }); + break; + case "ne": + this._elem.css({ right: 0, top: aj.top }); + break; + case "e": + var ah = + (aj.top + + (this._plotDimensions.height - aj.bottom)) / + 2 - + this.getHeight() / 2; + this._elem.css({ right: aj.right, top: ah }); + break; + case "se": + this._elem.css({ + right: aj.right, + bottom: aj.bottom, + }); + break; + case "s": + var ai = + (aj.left + + (this._plotDimensions.width - aj.right)) / + 2 - + this.getWidth() / 2; + this._elem.css({ left: ai, bottom: aj.bottom }); + break; + case "sw": + this._elem.css({ + left: aj.left, + bottom: aj.bottom, + }); + break; + case "w": + var ah = + (aj.top + + (this._plotDimensions.height - aj.bottom)) / + 2 - + this.getHeight() / 2; + this._elem.css({ left: aj.left, top: ah }); + break; + default: + this._elem.css({ + right: aj.right, + bottom: aj.bottom, + }); + break; + } + } + } + } + }; + L.jqplot.ThemeEngine = function () { + this.themes = {}; + this.activeTheme = null; + }; + L.jqplot.ThemeEngine.prototype.init = function () { + var ak = new L.jqplot.Theme({ _name: "Default" }); + var an, ai, am; + for (an in ak.target) { + if (an == "textColor") { + ak.target[an] = this.target.css("color"); + } else { + ak.target[an] = this.target.css(an); + } + } + if (this.title.show && this.title._elem) { + for (an in ak.title) { + if (an == "textColor") { + ak.title[an] = this.title._elem.css("color"); + } else { + ak.title[an] = this.title._elem.css(an); + } + } + } + for (an in ak.grid) { + ak.grid[an] = this.grid[an]; + } + if (ak.grid.backgroundColor == null && this.grid.background != null) { + ak.grid.backgroundColor = this.grid.background; + } + if (this.legend.show && this.legend._elem) { + for (an in ak.legend) { + if (an == "textColor") { + ak.legend[an] = this.legend._elem.css("color"); + } else { + ak.legend[an] = this.legend._elem.css(an); + } + } + } + var aj; + for (ai = 0; ai < this.series.length; ai++) { + aj = this.series[ai]; + if (aj.renderer.constructor == L.jqplot.LineRenderer) { + ak.series.push(new p()); + } else { + if (aj.renderer.constructor == L.jqplot.BarRenderer) { + ak.series.push(new T()); + } else { + if (aj.renderer.constructor == L.jqplot.PieRenderer) { + ak.series.push(new f()); + } else { + if (aj.renderer.constructor == L.jqplot.DonutRenderer) { + ak.series.push(new G()); + } else { + if ( + aj.renderer.constructor == + L.jqplot.FunnelRenderer + ) { + ak.series.push(new Z()); + } else { + if ( + aj.renderer.constructor == + L.jqplot.MeterGaugeRenderer + ) { + ak.series.push(new D()); + } else { + ak.series.push({}); + } + } + } + } + } + } + for (an in ak.series[ai]) { + ak.series[ai][an] = aj[an]; + } + } + var ah, al; + for (an in this.axes) { + al = this.axes[an]; + ah = ak.axes[an] = new P(); + ah.borderColor = al.borderColor; + ah.borderWidth = al.borderWidth; + if (al._ticks && al._ticks[0]) { + for (am in ah.ticks) { + if (al._ticks[0].hasOwnProperty(am)) { + ah.ticks[am] = al._ticks[0][am]; + } else { + if (al._ticks[0]._elem) { + ah.ticks[am] = al._ticks[0]._elem.css(am); + } + } + } + } + if (al._label && al._label.show) { + for (am in ah.label) { + if (al._label[am]) { + ah.label[am] = al._label[am]; + } else { + if (al._label._elem) { + if (am == "textColor") { + ah.label[am] = al._label._elem.css("color"); + } else { + ah.label[am] = al._label._elem.css(am); + } + } + } + } + } + } + this.themeEngine._add(ak); + this.themeEngine.activeTheme = this.themeEngine.themes[ak._name]; + }; + L.jqplot.ThemeEngine.prototype.get = function (ah) { + if (!ah) { + return this.activeTheme; + } else { + return this.themes[ah]; + } + }; + function O(ai, ah) { + return ai - ah; + } + L.jqplot.ThemeEngine.prototype.getThemeNames = function () { + var ah = []; + for (var ai in this.themes) { + ah.push(ai); + } + return ah.sort(O); + }; + L.jqplot.ThemeEngine.prototype.getThemes = function () { + var ai = []; + var ah = []; + for (var ak in this.themes) { + ai.push(ak); + } + ai.sort(O); + for (var aj = 0; aj < ai.length; aj++) { + ah.push(this.themes[ai[aj]]); + } + return ah; + }; + L.jqplot.ThemeEngine.prototype.activate = function (av, aB) { + var ah = false; + if (!aB && this.activeTheme && this.activeTheme._name) { + aB = this.activeTheme._name; + } + if (!this.themes.hasOwnProperty(aB)) { + throw new Error("No theme of that name"); + } else { + var am = this.themes[aB]; + this.activeTheme = am; + var aA, + at = false, + ar = false; + var ai = ["xaxis", "x2axis", "yaxis", "y2axis"]; + for (aw = 0; aw < ai.length; aw++) { + var an = ai[aw]; + if (am.axesStyles.borderColor != null) { + av.axes[an].borderColor = am.axesStyles.borderColor; + } + if (am.axesStyles.borderWidth != null) { + av.axes[an].borderWidth = am.axesStyles.borderWidth; + } + } + for (var az in av.axes) { + var ak = av.axes[az]; + if (ak.show) { + var aq = am.axes[az] || {}; + var ao = am.axesStyles; + var al = L.jqplot.extend(true, {}, aq, ao); + aA = + am.axesStyles.borderColor != null + ? am.axesStyles.borderColor + : al.borderColor; + if (al.borderColor != null) { + ak.borderColor = al.borderColor; + ah = true; + } + aA = + am.axesStyles.borderWidth != null + ? am.axesStyles.borderWidth + : al.borderWidth; + if (al.borderWidth != null) { + ak.borderWidth = al.borderWidth; + ah = true; + } + if (ak._ticks && ak._ticks[0]) { + for (var aj in al.ticks) { + aA = al.ticks[aj]; + if (aA != null) { + ak.tickOptions[aj] = aA; + ak._ticks = []; + ah = true; + } + } + } + if (ak._label && ak._label.show) { + for (var aj in al.label) { + aA = al.label[aj]; + if (aA != null) { + ak.labelOptions[aj] = aA; + ah = true; + } + } + } + } + } + for (var au in am.grid) { + if (am.grid[au] != null) { + av.grid[au] = am.grid[au]; + } + } + if (!ah) { + av.grid.draw(); + } + if (av.legend.show) { + for (au in am.legend) { + if (am.legend[au] != null) { + av.legend[au] = am.legend[au]; + } + } + } + if (av.title.show) { + for (au in am.title) { + if (am.title[au] != null) { + av.title[au] = am.title[au]; + } + } + } + var aw; + for (aw = 0; aw < am.series.length; aw++) { + var ap = {}; + var ay = false; + for (au in am.series[aw]) { + aA = + am.seriesStyles[au] != null + ? am.seriesStyles[au] + : am.series[aw][au]; + if (aA != null) { + ap[au] = aA; + if (au == "color") { + av.series[aw].renderer.shapeRenderer.fillStyle = aA; + av.series[aw].renderer.shapeRenderer.strokeStyle = + aA; + av.series[aw][au] = aA; + } else { + if (au == "lineWidth" || au == "linePattern") { + av.series[aw].renderer.shapeRenderer[au] = aA; + av.series[aw][au] = aA; + } else { + if (au == "markerOptions") { + V(av.series[aw].markerOptions, aA); + V(av.series[aw].markerRenderer, aA); + } else { + av.series[aw][au] = aA; + } + } + } + ah = true; + } + } + } + if (ah) { + av.target.empty(); + av.draw(); + } + for (au in am.target) { + if (am.target[au] != null) { + av.target.css(au, am.target[au]); + } + } + } + }; + L.jqplot.ThemeEngine.prototype._add = function (ai, ah) { + if (ah) { + ai._name = ah; + } + if (!ai._name) { + ai._name = Date.parse(new Date()); + } + if (!this.themes.hasOwnProperty(ai._name)) { + this.themes[ai._name] = ai; + } else { + throw new Error("jqplot.ThemeEngine Error: Theme already in use"); + } + }; + L.jqplot.ThemeEngine.prototype.remove = function (ah) { + if (ah == "Default") { + return false; + } + return delete this.themes[ah]; + }; + L.jqplot.ThemeEngine.prototype.newTheme = function (ah, aj) { + if (typeof ah == "object") { + aj = aj || ah; + ah = null; + } + if (aj && aj._name) { + ah = aj._name; + } else { + ah = ah || Date.parse(new Date()); + } + var ai = this.copy(this.themes.Default._name, ah); + L.jqplot.extend(ai, aj); + return ai; + }; + function B(aj) { + if (aj == null || typeof aj != "object") { + return aj; + } + var ah = new aj.constructor(); + for (var ai in aj) { + ah[ai] = B(aj[ai]); + } + return ah; + } + L.jqplot.clone = B; + function V(aj, ai) { + if (ai == null || typeof ai != "object") { + return; + } + for (var ah in ai) { + if (ah == "highlightColors") { + aj[ah] = B(ai[ah]); + } + if (ai[ah] != null && typeof ai[ah] == "object") { + if (!aj.hasOwnProperty(ah)) { + aj[ah] = {}; + } + V(aj[ah], ai[ah]); + } else { + aj[ah] = ai[ah]; + } + } + } + L.jqplot.merge = V; + L.jqplot.extend = function () { + var am = arguments[0] || {}, + ak = 1, + al = arguments.length, + ah = false, + aj; + if (typeof am === "boolean") { + ah = am; + am = arguments[1] || {}; + ak = 2; + } + if ( + typeof am !== "object" && + !toString.call(am) === "[object Function]" + ) { + am = {}; + } + for (; ak < al; ak++) { + if ((aj = arguments[ak]) != null) { + for (var ai in aj) { + var an = am[ai], + ao = aj[ai]; + if (am === ao) { + continue; + } + if (ah && ao && typeof ao === "object" && !ao.nodeType) { + am[ai] = L.jqplot.extend( + ah, + an || (ao.length != null ? [] : {}), + ao, + ); + } else { + if (ao !== u) { + am[ai] = ao; + } + } + } + } + } + return am; + }; + L.jqplot.ThemeEngine.prototype.rename = function (ai, ah) { + if (ai == "Default" || ah == "Default") { + throw new Error( + "jqplot.ThemeEngine Error: Cannot rename from/to Default", + ); + } + if (this.themes.hasOwnProperty(ah)) { + throw new Error( + "jqplot.ThemeEngine Error: New name already in use.", + ); + } else { + if (this.themes.hasOwnProperty(ai)) { + var aj = this.copy(ai, ah); + this.remove(ai); + return aj; + } + } + throw new Error( + "jqplot.ThemeEngine Error: Old name or new name invalid", + ); + }; + L.jqplot.ThemeEngine.prototype.copy = function (ah, aj, al) { + if (aj == "Default") { + throw new Error( + "jqplot.ThemeEngine Error: Cannot copy over Default theme", + ); + } + if (!this.themes.hasOwnProperty(ah)) { + var ai = "jqplot.ThemeEngine Error: Source name invalid"; + throw new Error(ai); + } + if (this.themes.hasOwnProperty(aj)) { + var ai = "jqplot.ThemeEngine Error: Target name invalid"; + throw new Error(ai); + } else { + var ak = B(this.themes[ah]); + ak._name = aj; + L.jqplot.extend(true, ak, al); + this._add(ak); + return ak; + } + }; + L.jqplot.Theme = function (ah, ai) { + if (typeof ah == "object") { + ai = ai || ah; + ah = null; + } + ah = ah || Date.parse(new Date()); + this._name = ah; + this.target = { backgroundColor: null }; + this.legend = { + textColor: null, + fontFamily: null, + fontSize: null, + border: null, + background: null, + }; + this.title = { + textColor: null, + fontFamily: null, + fontSize: null, + textAlign: null, + }; + this.seriesStyles = {}; + this.series = []; + this.grid = { + drawGridlines: null, + gridLineColor: null, + gridLineWidth: null, + backgroundColor: null, + borderColor: null, + borderWidth: null, + shadow: null, + }; + this.axesStyles = { label: {}, ticks: {} }; + this.axes = {}; + if (typeof ai == "string") { + this._name = ai; + } else { + if (typeof ai == "object") { + L.jqplot.extend(true, this, ai); + } + } + }; + var P = function () { + this.borderColor = null; + this.borderWidth = null; + this.ticks = new o(); + this.label = new t(); + }; + var o = function () { + this.show = null; + this.showGridline = null; + this.showLabel = null; + this.showMark = null; + this.size = null; + this.textColor = null; + this.whiteSpace = null; + this.fontSize = null; + this.fontFamily = null; + }; + var t = function () { + this.textColor = null; + this.whiteSpace = null; + this.fontSize = null; + this.fontFamily = null; + this.fontWeight = null; + }; + var p = function () { + this.color = null; + this.lineWidth = null; + this.linePattern = null; + this.shadow = null; + this.fillColor = null; + this.showMarker = null; + this.markerOptions = new I(); + }; + var I = function () { + this.show = null; + this.style = null; + this.lineWidth = null; + this.size = null; + this.color = null; + this.shadow = null; + }; + var T = function () { + this.color = null; + this.seriesColors = null; + this.lineWidth = null; + this.shadow = null; + this.barPadding = null; + this.barMargin = null; + this.barWidth = null; + this.highlightColors = null; + }; + var f = function () { + this.seriesColors = null; + this.padding = null; + this.sliceMargin = null; + this.fill = null; + this.shadow = null; + this.startAngle = null; + this.lineWidth = null; + this.highlightColors = null; + }; + var G = function () { + this.seriesColors = null; + this.padding = null; + this.sliceMargin = null; + this.fill = null; + this.shadow = null; + this.startAngle = null; + this.lineWidth = null; + this.innerDiameter = null; + this.thickness = null; + this.ringMargin = null; + this.highlightColors = null; + }; + var Z = function () { + this.color = null; + this.lineWidth = null; + this.shadow = null; + this.padding = null; + this.sectionMargin = null; + this.seriesColors = null; + this.highlightColors = null; + }; + var D = function () { + this.padding = null; + this.backgroundColor = null; + this.ringColor = null; + this.tickColor = null; + this.ringWidth = null; + this.intervalColors = null; + this.intervalInnerRadius = null; + this.intervalOuterRadius = null; + this.hubRadius = null; + this.needleThickness = null; + this.needlePad = null; + }; + L.fn.jqplotChildText = function () { + return L(this) + .contents() + .filter(function () { + return this.nodeType == 3; + }) + .text(); + }; + L.fn.jqplotGetComputedFontStyle = function () { + var ak = window.getComputedStyle + ? window.getComputedStyle(this[0], "") + : this[0].currentStyle; + var ai = ak["font-style"] + ? ["font-style", "font-weight", "font-size", "font-family"] + : ["fontStyle", "fontWeight", "fontSize", "fontFamily"]; + var al = []; + for (var aj = 0; aj < ai.length; ++aj) { + var ah = String(ak[ai[aj]]); + if (ah && ah != "normal") { + al.push(ah); + } + } + return al.join(" "); + }; + L.fn.jqplotToImageCanvas = function (aj) { + aj = aj || {}; + var av = aj.x_offset == null ? 0 : aj.x_offset; + var ax = aj.y_offset == null ? 0 : aj.y_offset; + var al = + aj.backgroundColor == null + ? "rgb(255,255,255)" + : aj.backgroundColor; + if (L(this).width() == 0 || L(this).height() == 0) { + return null; + } + if (L.jqplot.use_excanvas) { + return null; + } + var an = document.createElement("canvas"); + var aA = L(this).outerHeight(true); + var at = L(this).outerWidth(true); + var am = L(this).offset(); + var ao = am.left; + var aq = am.top; + var au = 0, + ar = 0; + var ay = [ + "jqplot-table-legend", + "jqplot-xaxis-tick", + "jqplot-x2axis-tick", + "jqplot-yaxis-tick", + "jqplot-y2axis-tick", + "jqplot-y3axis-tick", + "jqplot-y4axis-tick", + "jqplot-y5axis-tick", + "jqplot-y6axis-tick", + "jqplot-y7axis-tick", + "jqplot-y8axis-tick", + "jqplot-y9axis-tick", + "jqplot-xaxis-label", + "jqplot-x2axis-label", + "jqplot-yaxis-label", + "jqplot-y2axis-label", + "jqplot-y3axis-label", + "jqplot-y4axis-label", + "jqplot-y5axis-label", + "jqplot-y6axis-label", + "jqplot-y7axis-label", + "jqplot-y8axis-label", + "jqplot-y9axis-label", + ]; + var ap, ah, ai, aB; + for (var az = 0; az < ay.length; az++) { + L(this) + .find("." + ay[az]) + .each(function () { + ap = L(this).offset().top - aq; + ah = L(this).offset().left - ao; + aB = ah + L(this).outerWidth(true) + au; + ai = ap + L(this).outerHeight(true) + ar; + if (ah < -au) { + at = at - au - ah; + au = -ah; + } + if (ap < -ar) { + aA = aA - ar - ap; + ar = -ap; + } + if (aB > at) { + at = aB; + } + if (ai > aA) { + aA = ai; + } + }); + } + an.width = at + Number(av); + an.height = aA + Number(ax); + var ak = an.getContext("2d"); + ak.save(); + ak.fillStyle = al; + ak.fillRect(0, 0, an.width, an.height); + ak.restore(); + ak.translate(au, ar); + ak.textAlign = "left"; + ak.textBaseline = "top"; + function aC(aE) { + var aF = parseInt(L(aE).css("line-height"), 10); + if (isNaN(aF)) { + aF = parseInt(L(aE).css("font-size"), 10) * 1.2; + } + return aF; + } + function aD(aF, aE, aS, aG, aO, aH) { + var aQ = aC(aF); + var aK = L(aF).innerWidth(); + var aL = L(aF).innerHeight(); + var aN = aS.split(/\s+/); + var aR = aN.length; + var aP = ""; + var aM = []; + var aU = aO; + var aT = aG; + for (var aJ = 0; aJ < aR; aJ++) { + aP += aN[aJ]; + if (aE.measureText(aP).width > aK) { + aM.push(aJ); + aP = ""; + aJ--; + } + } + if (aM.length === 0) { + if (L(aF).css("textAlign") === "center") { + aT = aG + (aH - aE.measureText(aP).width) / 2 - au; + } + aE.fillText(aS, aT, aO); + } else { + aP = aN.slice(0, aM[0]).join(" "); + if (L(aF).css("textAlign") === "center") { + aT = aG + (aH - aE.measureText(aP).width) / 2 - au; + } + aE.fillText(aP, aT, aU); + aU += aQ; + for (var aJ = 1, aI = aM.length; aJ < aI; aJ++) { + aP = aN.slice(aM[aJ - 1], aM[aJ]).join(" "); + if (L(aF).css("textAlign") === "center") { + aT = aG + (aH - aE.measureText(aP).width) / 2 - au; + } + aE.fillText(aP, aT, aU); + aU += aQ; + } + aP = aN.slice(aM[aJ - 1], aN.length).join(" "); + if (L(aF).css("textAlign") === "center") { + aT = aG + (aH - aE.measureText(aP).width) / 2 - au; + } + aE.fillText(aP, aT, aU); + } + } + function aw(aG, aJ, aE) { + var aN = aG.tagName.toLowerCase(); + var aF = L(aG).position(); + var aK = window.getComputedStyle + ? window.getComputedStyle(aG, "") + : aG.currentStyle; + var aI = + aJ + + aF.left + + parseInt(aK.marginLeft, 10) + + parseInt(aK.borderLeftWidth, 10) + + parseInt(aK.paddingLeft, 10); + var aL = + aE + + aF.top + + parseInt(aK.marginTop, 10) + + parseInt(aK.borderTopWidth, 10) + + parseInt(aK.paddingTop, 10); + var aM = an.width; + if ( + (aN == "div" || aN == "span") && + !L(aG).hasClass("jqplot-highlighter-tooltip") + ) { + L(aG) + .children() + .each(function () { + aw(this, aI, aL); + }); + var aO = L(aG).jqplotChildText(); + if (aO) { + ak.font = L(aG).jqplotGetComputedFontStyle(); + ak.fillStyle = L(aG).css("color"); + aD(aG, ak, aO, aI, aL, aM); + } + } else { + if (aN === "table" && L(aG).hasClass("jqplot-table-legend")) { + ak.strokeStyle = L(aG).css("border-top-color"); + ak.fillStyle = L(aG).css("background-color"); + ak.fillRect( + aI, + aL, + L(aG).innerWidth(), + L(aG).innerHeight(), + ); + if (parseInt(L(aG).css("border-top-width"), 10) > 0) { + ak.strokeRect( + aI, + aL, + L(aG).innerWidth(), + L(aG).innerHeight(), + ); + } + L(aG) + .find("div.jqplot-table-legend-swatch-outline") + .each(function () { + var aU = L(this); + ak.strokeStyle = aU.css("border-top-color"); + var aQ = aI + aU.position().left; + var aR = aL + aU.position().top; + ak.strokeRect( + aQ, + aR, + aU.innerWidth(), + aU.innerHeight(), + ); + aQ += parseInt(aU.css("padding-left"), 10); + aR += parseInt(aU.css("padding-top"), 10); + var aT = + aU.innerHeight() - + 2 * parseInt(aU.css("padding-top"), 10); + var aP = + aU.innerWidth() - + 2 * parseInt(aU.css("padding-left"), 10); + var aS = aU.children( + "div.jqplot-table-legend-swatch", + ); + ak.fillStyle = aS.css("background-color"); + ak.fillRect(aQ, aR, aP, aT); + }); + L(aG) + .find("td.jqplot-table-legend-label") + .each(function () { + var aR = L(this); + var aP = aI + aR.position().left; + var aQ = + aL + + aR.position().top + + parseInt(aR.css("padding-top"), 10); + ak.font = aR.jqplotGetComputedFontStyle(); + ak.fillStyle = aR.css("color"); + aD(aR, ak, aR.text(), aP, aQ, aM); + }); + var aH = null; + } else { + if (aN == "canvas") { + ak.drawImage(aG, aI, aL); + } + } + } + } + L(this) + .children() + .each(function () { + aw(this, av, ax); + }); + return an; + }; + L.fn.jqplotToImageStr = function (ai) { + var ah = L(this).jqplotToImageCanvas(ai); + if (ah) { + return ah.toDataURL("image/png"); + } else { + return null; + } + }; + L.fn.jqplotToImageElem = function (ah) { + var ai = document.createElement("img"); + var aj = L(this).jqplotToImageStr(ah); + ai.src = aj; + return ai; + }; + L.fn.jqplotToImageElemStr = function (ah) { + var ai = ""; + return ai; + }; + L.fn.jqplotSaveImage = function () { + var ah = L(this).jqplotToImageStr({}); + if (ah) { + window.location.href = ah.replace( + "image/png", + "image/octet-stream", + ); + } + }; + L.fn.jqplotViewImage = function () { + var ai = L(this).jqplotToImageElemStr({}); + var aj = L(this).jqplotToImageStr({}); + if (ai) { + var ah = window.open(""); + ah.document.open("image/png"); + ah.document.write(ai); + ah.document.close(); + ah = null; + } + }; + var ag = function () { + this.syntax = ag.config.syntax; + this._type = "jsDate"; + this.proxy = new Date(); + this.options = {}; + this.locale = ag.regional.getLocale(); + this.formatString = ""; + this.defaultCentury = ag.config.defaultCentury; + switch (arguments.length) { + case 0: + break; + case 1: + if ( + l(arguments[0]) == "[object Object]" && + arguments[0]._type != "jsDate" + ) { + var aj = (this.options = arguments[0]); + this.syntax = aj.syntax || this.syntax; + this.defaultCentury = + aj.defaultCentury || this.defaultCentury; + this.proxy = ag.createDate(aj.date); + } else { + this.proxy = ag.createDate(arguments[0]); + } + break; + default: + var ah = []; + for (var ai = 0; ai < arguments.length; ai++) { + ah.push(arguments[ai]); + } + this.proxy = new Date(); + this.proxy.setFullYear.apply(this.proxy, ah.slice(0, 3)); + if (ah.slice(3).length) { + this.proxy.setHours.apply(this.proxy, ah.slice(3)); + } + break; + } + }; + ag.config = { defaultLocale: "en", syntax: "perl", defaultCentury: 1900 }; + ag.prototype.add = function (aj, ai) { + var ah = E[ai] || E.day; + if (typeof ah == "number") { + this.proxy.setTime(this.proxy.getTime() + ah * aj); + } else { + ah.add(this, aj); + } + return this; + }; + ag.prototype.clone = function () { + return new ag(this.proxy.getTime()); + }; + ag.prototype.getUtcOffset = function () { + return this.proxy.getTimezoneOffset() * 60000; + }; + ag.prototype.diff = function (ai, al, ah) { + ai = new ag(ai); + if (ai === null) { + return null; + } + var aj = E[al] || E.day; + if (typeof aj == "number") { + var ak = (this.proxy.getTime() - ai.proxy.getTime()) / aj; + } else { + var ak = aj.diff(this.proxy, ai.proxy); + } + return ah ? ak : Math[ak > 0 ? "floor" : "ceil"](ak); + }; + ag.prototype.getAbbrDayName = function () { + return ag.regional[this.locale]["dayNamesShort"][this.proxy.getDay()]; + }; + ag.prototype.getAbbrMonthName = function () { + return ag.regional[this.locale]["monthNamesShort"][ + this.proxy.getMonth() + ]; + }; + ag.prototype.getAMPM = function () { + return this.proxy.getHours() >= 12 ? "PM" : "AM"; + }; + ag.prototype.getAmPm = function () { + return this.proxy.getHours() >= 12 ? "pm" : "am"; + }; + ag.prototype.getCentury = function () { + return parseInt(this.proxy.getFullYear() / 100, 10); + }; + ag.prototype.getDate = function () { + return this.proxy.getDate(); + }; + ag.prototype.getDay = function () { + return this.proxy.getDay(); + }; + ag.prototype.getDayOfWeek = function () { + var ah = this.proxy.getDay(); + return ah === 0 ? 7 : ah; + }; + ag.prototype.getDayOfYear = function () { + var ai = this.proxy; + var ah = ai - new Date("" + ai.getFullYear() + "/1/1 GMT"); + ah += ai.getTimezoneOffset() * 60000; + ai = null; + return parseInt(ah / 60000 / 60 / 24, 10) + 1; + }; + ag.prototype.getDayName = function () { + return ag.regional[this.locale]["dayNames"][this.proxy.getDay()]; + }; + ag.prototype.getFullWeekOfYear = function () { + var ak = this.proxy; + var ah = this.getDayOfYear(); + var aj = 6 - ak.getDay(); + var ai = parseInt((ah + aj) / 7, 10); + return ai; + }; + ag.prototype.getFullYear = function () { + return this.proxy.getFullYear(); + }; + ag.prototype.getGmtOffset = function () { + var ah = this.proxy.getTimezoneOffset() / 60; + var ai = ah < 0 ? "+" : "-"; + ah = Math.abs(ah); + return ai + N(Math.floor(ah), 2) + ":" + N((ah % 1) * 60, 2); + }; + ag.prototype.getHours = function () { + return this.proxy.getHours(); + }; + ag.prototype.getHours12 = function () { + var ah = this.proxy.getHours(); + return ah > 12 ? ah - 12 : ah == 0 ? 12 : ah; + }; + ag.prototype.getIsoWeek = function () { + var ak = this.proxy; + var aj = this.getWeekOfYear(); + var ah = new Date("" + ak.getFullYear() + "/1/1").getDay(); + var ai = aj + (ah > 4 || ah <= 1 ? 0 : 1); + if ( + ai == 53 && + new Date("" + ak.getFullYear() + "/12/31").getDay() < 4 + ) { + ai = 1; + } else { + if (ai === 0) { + ak = new ag(new Date("" + (ak.getFullYear() - 1) + "/12/31")); + ai = ak.getIsoWeek(); + } + } + ak = null; + return ai; + }; + ag.prototype.getMilliseconds = function () { + return this.proxy.getMilliseconds(); + }; + ag.prototype.getMinutes = function () { + return this.proxy.getMinutes(); + }; + ag.prototype.getMonth = function () { + return this.proxy.getMonth(); + }; + ag.prototype.getMonthName = function () { + return ag.regional[this.locale]["monthNames"][this.proxy.getMonth()]; + }; + ag.prototype.getMonthNumber = function () { + return this.proxy.getMonth() + 1; + }; + ag.prototype.getSeconds = function () { + return this.proxy.getSeconds(); + }; + ag.prototype.getShortYear = function () { + return this.proxy.getYear() % 100; + }; + ag.prototype.getTime = function () { + return this.proxy.getTime(); + }; + ag.prototype.getTimezoneAbbr = function () { + return this.proxy.toString().replace(/^.*\(([^)]+)\)$/, "$1"); + }; + ag.prototype.getTimezoneName = function () { + var ah = /(?:\((.+)\)$| ([A-Z]{3}) )/.exec(this.toString()); + return ah[1] || ah[2] || "GMT" + this.getGmtOffset(); + }; + ag.prototype.getTimezoneOffset = function () { + return this.proxy.getTimezoneOffset(); + }; + ag.prototype.getWeekOfYear = function () { + var ah = this.getDayOfYear(); + var aj = 7 - this.getDayOfWeek(); + var ai = parseInt((ah + aj) / 7, 10); + return ai; + }; + ag.prototype.getUnix = function () { + return Math.round(this.proxy.getTime() / 1000, 0); + }; + ag.prototype.getYear = function () { + return this.proxy.getYear(); + }; + ag.prototype.next = function (ah) { + ah = ah || "day"; + return this.clone().add(1, ah); + }; + ag.prototype.set = function () { + switch (arguments.length) { + case 0: + this.proxy = new Date(); + break; + case 1: + if ( + l(arguments[0]) == "[object Object]" && + arguments[0]._type != "jsDate" + ) { + var aj = (this.options = arguments[0]); + this.syntax = aj.syntax || this.syntax; + this.defaultCentury = + aj.defaultCentury || this.defaultCentury; + this.proxy = ag.createDate(aj.date); + } else { + this.proxy = ag.createDate(arguments[0]); + } + break; + default: + var ah = []; + for (var ai = 0; ai < arguments.length; ai++) { + ah.push(arguments[ai]); + } + this.proxy = new Date(); + this.proxy.setFullYear.apply(this.proxy, ah.slice(0, 3)); + if (ah.slice(3).length) { + this.proxy.setHours.apply(this.proxy, ah.slice(3)); + } + break; + } + return this; + }; + ag.prototype.setDate = function (ah) { + this.proxy.setDate(ah); + return this; + }; + ag.prototype.setFullYear = function () { + this.proxy.setFullYear.apply(this.proxy, arguments); + return this; + }; + ag.prototype.setHours = function () { + this.proxy.setHours.apply(this.proxy, arguments); + return this; + }; + ag.prototype.setMilliseconds = function (ah) { + this.proxy.setMilliseconds(ah); + return this; + }; + ag.prototype.setMinutes = function () { + this.proxy.setMinutes.apply(this.proxy, arguments); + return this; + }; + ag.prototype.setMonth = function () { + this.proxy.setMonth.apply(this.proxy, arguments); + return this; + }; + ag.prototype.setSeconds = function () { + this.proxy.setSeconds.apply(this.proxy, arguments); + return this; + }; + ag.prototype.setTime = function (ah) { + this.proxy.setTime(ah); + return this; + }; + ag.prototype.setYear = function () { + this.proxy.setYear.apply(this.proxy, arguments); + return this; + }; + ag.prototype.strftime = function (ah) { + ah = + ah || this.formatString || ag.regional[this.locale]["formatString"]; + return ag.strftime(this, ah, this.syntax); + }; + ag.prototype.toString = function () { + return this.proxy.toString(); + }; + ag.prototype.toYmdInt = function () { + return ( + this.proxy.getFullYear() * 10000 + + this.getMonthNumber() * 100 + + this.proxy.getDate() + ); + }; + ag.regional = { + en: { + monthNames: [ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December", + ], + monthNamesShort: [ + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec", + ], + dayNames: [ + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday", + ], + dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], + formatString: "%Y-%m-%d %H:%M:%S", + }, + fr: { + monthNames: [ + "Janvier", + "Février", + "Mars", + "Avril", + "Mai", + "Juin", + "Juillet", + "Août", + "Septembre", + "Octobre", + "Novembre", + "Décembre", + ], + monthNamesShort: [ + "Jan", + "Fév", + "Mar", + "Avr", + "Mai", + "Jun", + "Jul", + "Aoû", + "Sep", + "Oct", + "Nov", + "Déc", + ], + dayNames: [ + "Dimanche", + "Lundi", + "Mardi", + "Mercredi", + "Jeudi", + "Vendredi", + "Samedi", + ], + dayNamesShort: ["Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam"], + formatString: "%Y-%m-%d %H:%M:%S", + }, + de: { + monthNames: [ + "Januar", + "Februar", + "März", + "April", + "Mai", + "Juni", + "Juli", + "August", + "September", + "Oktober", + "November", + "Dezember", + ], + monthNamesShort: [ + "Jan", + "Feb", + "Mär", + "Apr", + "Mai", + "Jun", + "Jul", + "Aug", + "Sep", + "Okt", + "Nov", + "Dez", + ], + dayNames: [ + "Sonntag", + "Montag", + "Dienstag", + "Mittwoch", + "Donnerstag", + "Freitag", + "Samstag", + ], + dayNamesShort: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"], + formatString: "%Y-%m-%d %H:%M:%S", + }, + es: { + monthNames: [ + "Enero", + "Febrero", + "Marzo", + "Abril", + "Mayo", + "Junio", + "Julio", + "Agosto", + "Septiembre", + "Octubre", + "Noviembre", + "Diciembre", + ], + monthNamesShort: [ + "Ene", + "Feb", + "Mar", + "Abr", + "May", + "Jun", + "Jul", + "Ago", + "Sep", + "Oct", + "Nov", + "Dic", + ], + dayNames: [ + "Domingo", + "Lunes", + "Martes", + "Miércoles", + "Jueves", + "Viernes", + "Sábado", + ], + dayNamesShort: [ + "Dom", + "Lun", + "Mar", + "Mié", + "Juv", + "Vie", + "Sáb", + ], + formatString: "%Y-%m-%d %H:%M:%S", + }, + ru: { + monthNames: [ + "Январь", + "Февраль", + "Март", + "Апрель", + "Май", + "Июнь", + "Июль", + "Август", + "Сентябрь", + "Октябрь", + "Ноябрь", + "Декабрь", + ], + monthNamesShort: [ + "Янв", + "Фев", + "Мар", + "Апр", + "Май", + "Июн", + "Июл", + "Авг", + "Сен", + "Окт", + "Ноя", + "Дек", + ], + dayNames: [ + "воскресенье", + "понедельник", + "вторник", + "среда", + "четверг", + "пятница", + "суббота", + ], + dayNamesShort: ["вск", "пнд", "втр", "срд", "чтв", "птн", "сбт"], + formatString: "%Y-%m-%d %H:%M:%S", + }, + ar: { + monthNames: [ + "كانون الثاني", + "شباط", + "آذار", + "نيسان", + "آذار", + "حزيران", + "تموز", + "آب", + "أيلول", + "تشرين الأول", + "تشرين الثاني", + "كانون الأول", + ], + monthNamesShort: [ + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10", + "11", + "12", + ], + dayNames: [ + "السبت", + "الأحد", + "الاثنين", + "الثلاثاء", + "الأربعاء", + "الخميس", + "الجمعة", + ], + dayNamesShort: [ + "سبت", + "أحد", + "اثنين", + "ثلاثاء", + "أربعاء", + "خميس", + "جمعة", + ], + formatString: "%Y-%m-%d %H:%M:%S", + }, + pt: { + monthNames: [ + "Janeiro", + "Fevereiro", + "Março", + "Abril", + "Maio", + "Junho", + "Julho", + "Agosto", + "Setembro", + "Outubro", + "Novembro", + "Dezembro", + ], + monthNamesShort: [ + "Jan", + "Fev", + "Mar", + "Abr", + "Mai", + "Jun", + "Jul", + "Ago", + "Set", + "Out", + "Nov", + "Dez", + ], + dayNames: [ + "Domingo", + "Segunda-feira", + "Terça-feira", + "Quarta-feira", + "Quinta-feira", + "Sexta-feira", + "Sábado", + ], + dayNamesShort: [ + "Dom", + "Seg", + "Ter", + "Qua", + "Qui", + "Sex", + "Sáb", + ], + formatString: "%Y-%m-%d %H:%M:%S", + }, + "pt-BR": { + monthNames: [ + "Janeiro", + "Fevereiro", + "Março", + "Abril", + "Maio", + "Junho", + "Julho", + "Agosto", + "Setembro", + "Outubro", + "Novembro", + "Dezembro", + ], + monthNamesShort: [ + "Jan", + "Fev", + "Mar", + "Abr", + "Mai", + "Jun", + "Jul", + "Ago", + "Set", + "Out", + "Nov", + "Dez", + ], + dayNames: [ + "Domingo", + "Segunda-feira", + "Terça-feira", + "Quarta-feira", + "Quinta-feira", + "Sexta-feira", + "Sábado", + ], + dayNamesShort: [ + "Dom", + "Seg", + "Ter", + "Qua", + "Qui", + "Sex", + "Sáb", + ], + formatString: "%Y-%m-%d %H:%M:%S", + }, + pl: { + monthNames: [ + "Styczeń", + "Luty", + "Marzec", + "Kwiecień", + "Maj", + "Czerwiec", + "Lipiec", + "Sierpień", + "Wrzesień", + "Październik", + "Listopad", + "Grudzień", + ], + monthNamesShort: [ + "Sty", + "Lut", + "Mar", + "Kwi", + "Maj", + "Cze", + "Lip", + "Sie", + "Wrz", + "Paź", + "Lis", + "Gru", + ], + dayNames: [ + "Niedziela", + "Poniedziałek", + "Wtorek", + "Środa", + "Czwartek", + "Piątek", + "Sobota", + ], + dayNamesShort: ["Ni", "Pn", "Wt", "Śr", "Cz", "Pt", "Sb"], + formatString: "%Y-%m-%d %H:%M:%S", + }, + nl: { + monthNames: [ + "Januari", + "Februari", + "Maart", + "April", + "Mei", + "Juni", + "July", + "Augustus", + "September", + "Oktober", + "November", + "December", + ], + monthNamesShort: [ + "Jan", + "Feb", + "Mar", + "Apr", + "Mei", + "Jun", + "Jul", + "Aug", + "Sep", + "Okt", + "Nov", + "Dec", + ], + dayNames: ","[ + ("Zondag", + "Maandag", + "Dinsdag", + "Woensdag", + "Donderdag", + "Vrijdag", + "Zaterdag") + ], + dayNamesShort: ["Zo", "Ma", "Di", "Wo", "Do", "Vr", "Za"], + formatString: "%Y-%m-%d %H:%M:%S", + }, + sv: { + monthNames: [ + "januari", + "februari", + "mars", + "april", + "maj", + "juni", + "juli", + "augusti", + "september", + "oktober", + "november", + "december", + ], + monthNamesShort: [ + "jan", + "feb", + "mar", + "apr", + "maj", + "jun", + "jul", + "aug", + "sep", + "okt", + "nov", + "dec", + ], + dayNames: [ + "söndag", + "måndag", + "tisdag", + "onsdag", + "torsdag", + "fredag", + "lördag", + ], + dayNamesShort: ["sön", "mån", "tis", "ons", "tor", "fre", "lör"], + formatString: "%Y-%m-%d %H:%M:%S", + }, + }; + ag.regional["en-US"] = ag.regional["en-GB"] = ag.regional.en; + ag.regional.getLocale = function () { + var ah = ag.config.defaultLocale; + if ( + document && + document.getElementsByTagName("html") && + document.getElementsByTagName("html")[0].lang + ) { + ah = document.getElementsByTagName("html")[0].lang; + if (!ag.regional.hasOwnProperty(ah)) { + ah = ag.config.defaultLocale; + } + } + return ah; + }; + var C = 24 * 60 * 60 * 1000; + var N = function (ah, ak) { + ah = String(ah); + var ai = ak - ah.length; + var aj = String(Math.pow(10, ai)).slice(1); + return aj.concat(ah); + }; + var E = { + millisecond: 1, + second: 1000, + minute: 60 * 1000, + hour: 60 * 60 * 1000, + day: C, + week: 7 * C, + month: { + add: function (aj, ah) { + E.year.add(aj, Math[ah > 0 ? "floor" : "ceil"](ah / 12)); + var ai = aj.getMonth() + (ah % 12); + if (ai == 12) { + ai = 0; + aj.setYear(aj.getFullYear() + 1); + } else { + if (ai == -1) { + ai = 11; + aj.setYear(aj.getFullYear() - 1); + } + } + aj.setMonth(ai); + }, + diff: function (al, aj) { + var ah = al.getFullYear() - aj.getFullYear(); + var ai = al.getMonth() - aj.getMonth() + ah * 12; + var ak = al.getDate() - aj.getDate(); + return ai + ak / 30; + }, + }, + year: { + add: function (ai, ah) { + ai.setYear( + ai.getFullYear() + Math[ah > 0 ? "floor" : "ceil"](ah), + ); + }, + diff: function (ai, ah) { + return E.month.diff(ai, ah) / 12; + }, + }, + }; + for (var Y in E) { + if (Y.substring(Y.length - 1) != "s") { + E[Y + "s"] = E[Y]; + } + } + var H = function (al, ak, ai) { + if (ag.formats[ai]["shortcuts"][ak]) { + return ag.strftime(al, ag.formats[ai]["shortcuts"][ak], ai); + } else { + var ah = (ag.formats[ai]["codes"][ak] || "").split("."); + var aj = al["get" + ah[0]] ? al["get" + ah[0]]() : ""; + if (ah[1]) { + aj = N(aj, ah[1]); + } + return aj; + } + }; + ag.strftime = function (an, ak, aj, ao) { + var ai = "perl"; + var am = ag.regional.getLocale(); + if (aj && ag.formats.hasOwnProperty(aj)) { + ai = aj; + } else { + if (aj && ag.regional.hasOwnProperty(aj)) { + am = aj; + } + } + if (ao && ag.formats.hasOwnProperty(ao)) { + ai = ao; + } else { + if (ao && ag.regional.hasOwnProperty(ao)) { + am = ao; + } + } + if (l(an) != "[object Object]" || an._type != "jsDate") { + an = new ag(an); + an.locale = am; + } + if (!ak) { + ak = an.formatString || ag.regional[am]["formatString"]; + } + var ah = ak || "%Y-%m-%d", + ap = "", + al; + while (ah.length > 0) { + if ((al = ah.match(ag.formats[ai].codes.matcher))) { + ap += ah.slice(0, al.index); + ap += (al[1] || "") + H(an, al[2], ai); + ah = ah.slice(al.index + al[0].length); + } else { + ap += ah; + ah = ""; + } + } + return ap; + }; + ag.formats = { ISO: "%Y-%m-%dT%H:%M:%S.%N%G", SQL: "%Y-%m-%d %H:%M:%S" }; + ag.formats.perl = { + codes: { + matcher: /()%(#?(%|[a-z]))/i, + Y: "FullYear", + y: "ShortYear.2", + m: "MonthNumber.2", + "#m": "MonthNumber", + B: "MonthName", + b: "AbbrMonthName", + d: "Date.2", + "#d": "Date", + e: "Date", + A: "DayName", + a: "AbbrDayName", + w: "Day", + H: "Hours.2", + "#H": "Hours", + I: "Hours12.2", + "#I": "Hours12", + p: "AMPM", + M: "Minutes.2", + "#M": "Minutes", + S: "Seconds.2", + "#S": "Seconds", + s: "Unix", + N: "Milliseconds.3", + "#N": "Milliseconds", + O: "TimezoneOffset", + Z: "TimezoneName", + G: "GmtOffset", + }, + shortcuts: { + F: "%Y-%m-%d", + T: "%H:%M:%S", + X: "%H:%M:%S", + x: "%m/%d/%y", + D: "%m/%d/%y", + "#c": "%a %b %e %H:%M:%S %Y", + v: "%e-%b-%Y", + R: "%H:%M", + r: "%I:%M:%S %p", + t: "\t", + n: "\n", + "%": "%", + }, + }; + ag.formats.php = { + codes: { + matcher: /()%((%|[a-z]))/i, + a: "AbbrDayName", + A: "DayName", + d: "Date.2", + e: "Date", + j: "DayOfYear.3", + u: "DayOfWeek", + w: "Day", + U: "FullWeekOfYear.2", + V: "IsoWeek.2", + W: "WeekOfYear.2", + b: "AbbrMonthName", + B: "MonthName", + m: "MonthNumber.2", + h: "AbbrMonthName", + C: "Century.2", + y: "ShortYear.2", + Y: "FullYear", + H: "Hours.2", + I: "Hours12.2", + l: "Hours12", + p: "AMPM", + P: "AmPm", + M: "Minutes.2", + S: "Seconds.2", + s: "Unix", + O: "TimezoneOffset", + z: "GmtOffset", + Z: "TimezoneAbbr", + }, + shortcuts: { + D: "%m/%d/%y", + F: "%Y-%m-%d", + T: "%H:%M:%S", + X: "%H:%M:%S", + x: "%m/%d/%y", + R: "%H:%M", + r: "%I:%M:%S %p", + t: "\t", + n: "\n", + "%": "%", + }, + }; + ag.createDate = function (aj) { + if (aj == null) { + return new Date(); + } + if (aj instanceof Date) { + return aj; + } + if (typeof aj == "number") { + return new Date(aj); + } + var ao = String(aj).replace(/^\s*(.+)\s*$/g, "$1"); + ao = ao.replace(/^([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,4})/, "$1/$2/$3"); + ao = ao.replace( + /^(3[01]|[0-2]?\d)[-\/]([a-z]{3,})[-\/](\d{4})/i, + "$1 $2 $3", + ); + var an = ao.match(/^(3[01]|[0-2]?\d)[-\/]([a-z]{3,})[-\/](\d{2})\D*/i); + if (an && an.length > 3) { + var at = parseFloat(an[3]); + var am = ag.config.defaultCentury + at; + am = String(am); + ao = ao.replace( + /^(3[01]|[0-2]?\d)[-\/]([a-z]{3,})[-\/](\d{2})\D*/i, + an[1] + " " + an[2] + " " + am, + ); + } + an = ao.match(/^([0-9]{1,2})[-\/]([0-9]{1,2})[-\/]([0-9]{1,2})[^0-9]/); + function ar(ax, aw) { + var aC = parseFloat(aw[1]); + var aB = parseFloat(aw[2]); + var aA = parseFloat(aw[3]); + var az = ag.config.defaultCentury; + var av, au, aD, ay; + if (aC > 31) { + au = aA; + aD = aB; + av = az + aC; + } else { + au = aB; + aD = aC; + av = az + aA; + } + ay = aD + "/" + au + "/" + av; + return ax.replace( + /^([0-9]{1,2})[-\/]([0-9]{1,2})[-\/]([0-9]{1,2})/, + ay, + ); + } + if (an && an.length > 3) { + ao = ar(ao, an); + } + var an = ao.match(/^([0-9]{1,2})[-\/]([0-9]{1,2})[-\/]([0-9]{1,2})$/); + if (an && an.length > 3) { + ao = ar(ao, an); + } + var al = 0; + var ai = ag.matchers.length; + var aq, + ah, + ap = ao, + ak; + while (al < ai) { + ah = Date.parse(ap); + if (!isNaN(ah)) { + return new Date(ah); + } + aq = ag.matchers[al]; + if (typeof aq == "function") { + ak = aq.call(ag, ap); + if (ak instanceof Date) { + return ak; + } + } else { + ap = ao.replace(aq[0], aq[1]); + } + al++; + } + return NaN; + }; + ag.daysInMonth = function (ah, ai) { + if (ai == 2) { + return new Date(ah, 1, 29).getDate() == 29 ? 29 : 28; + } + return [u, 31, u, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][ai]; + }; + ag.matchers = [ + [/(3[01]|[0-2]\d)\s*\.\s*(1[0-2]|0\d)\s*\.\s*([1-9]\d{3})/, "$2/$1/$3"], + [/([1-9]\d{3})\s*-\s*(1[0-2]|0\d)\s*-\s*(3[01]|[0-2]\d)/, "$2/$3/$1"], + function (ak) { + var ai = ak.match( + /^(?:(.+)\s+)?([012]?\d)(?:\s*\:\s*(\d\d))?(?:\s*\:\s*(\d\d(\.\d*)?))?\s*(am|pm)?\s*$/i, + ); + if (ai) { + if (ai[1]) { + var aj = this.createDate(ai[1]); + if (isNaN(aj)) { + return; + } + } else { + var aj = new Date(); + aj.setMilliseconds(0); + } + var ah = parseFloat(ai[2]); + if (ai[6]) { + ah = + ai[6].toLowerCase() == "am" + ? ah == 12 + ? 0 + : ah + : ah == 12 + ? 12 + : ah + 12; + } + aj.setHours( + ah, + parseInt(ai[3] || 0, 10), + parseInt(ai[4] || 0, 10), + (parseFloat(ai[5] || 0) || 0) * 1000, + ); + return aj; + } else { + return ak; + } + }, + function (ak) { + var ai = ak.match( + /^(?:(.+))[T|\s+]([012]\d)(?:\:(\d\d))(?:\:(\d\d))(?:\.\d+)([\+\-]\d\d\:\d\d)$/i, + ); + if (ai) { + if (ai[1]) { + var aj = this.createDate(ai[1]); + if (isNaN(aj)) { + return; + } + } else { + var aj = new Date(); + aj.setMilliseconds(0); + } + var ah = parseFloat(ai[2]); + aj.setHours( + ah, + parseInt(ai[3], 10), + parseInt(ai[4], 10), + parseFloat(ai[5]) * 1000, + ); + return aj; + } else { + return ak; + } + }, + function (al) { + var aj = al.match( + /^([0-3]?\d)\s*[-\/.\s]{1}\s*([a-zA-Z]{3,9})\s*[-\/.\s]{1}\s*([0-3]?\d)$/, + ); + if (aj) { + var ak = new Date(); + var am = ag.config.defaultCentury; + var ao = parseFloat(aj[1]); + var an = parseFloat(aj[3]); + var ai, ah, ap; + if (ao > 31) { + ah = an; + ai = am + ao; + } else { + ah = ao; + ai = am + an; + } + var ap = ab( + aj[2], + ag.regional[ag.regional.getLocale()]["monthNamesShort"], + ); + if (ap == -1) { + ap = ab( + aj[2], + ag.regional[ag.regional.getLocale()]["monthNames"], + ); + } + ak.setFullYear(ai, ap, ah); + ak.setHours(0, 0, 0, 0); + return ak; + } else { + return al; + } + }, + ]; + function ab(aj, ak) { + if (ak.indexOf) { + return ak.indexOf(aj); + } + for (var ah = 0, ai = ak.length; ah < ai; ah++) { + if (ak[ah] === aj) { + return ah; + } + } + return -1; + } + function l(ah) { + if (ah === null) { + return "[object Null]"; + } + return Object.prototype.toString.call(ah); + } + L.jsDate = ag; + L.jqplot.sprintf = function () { + function an(au, ap, aq, at) { + var ar = + au.length >= ap + ? "" + : Array((1 + ap - au.length) >>> 0).join(aq); + return at ? au + ar : ar + au; + } + function ak(ar) { + var aq = new String(ar); + for (var ap = 10; ap > 0; ap--) { + if ( + aq == + (aq = aq.replace( + /^(\d+)(\d{3})/, + "$1" + L.jqplot.sprintf.thousandsSeparator + "$2", + )) + ) { + break; + } + } + return aq; + } + function aj(av, au, ax, ar, at, aq) { + var aw = ar - av.length; + if (aw > 0) { + var ap = " "; + if (aq) { + ap = " "; + } + if (ax || !at) { + av = an(av, ar, ap, ax); + } else { + av = + av.slice(0, au.length) + + an("", aw, "0", true) + + av.slice(au.length); + } + } + return av; + } + function ao(ay, aq, aw, ar, ap, av, ax, au) { + var at = ay >>> 0; + aw = (aw && at && { 2: "0b", 8: "0", 16: "0x" }[aq]) || ""; + ay = aw + an(at.toString(aq), av || 0, "0", false); + return aj(ay, aw, ar, ap, ax, au); + } + function ah(au, av, ar, ap, at, aq) { + if (ap != null) { + au = au.slice(0, ap); + } + return aj(au, "", av, ar, at, aq); + } + var ai = arguments, + al = 0, + am = ai[al++]; + return am.replace( + L.jqplot.sprintf.regex, + function (aM, ax, ay, aB, aO, aJ, av) { + if (aM == "%%") { + return "%"; + } + var aD = false, + az = "", + aA = false, + aL = false, + aw = false, + au = false; + for (var aI = 0; ay && aI < ay.length; aI++) { + switch (ay.charAt(aI)) { + case " ": + az = " "; + break; + case "+": + az = "+"; + break; + case "-": + aD = true; + break; + case "0": + aA = true; + break; + case "#": + aL = true; + break; + case "&": + aw = true; + break; + case "'": + au = true; + break; + } + } + if (!aB) { + aB = 0; + } else { + if (aB == "*") { + aB = +ai[al++]; + } else { + if (aB.charAt(0) == "*") { + aB = +ai[aB.slice(1, -1)]; + } else { + aB = +aB; + } + } + } + if (aB < 0) { + aB = -aB; + aD = true; + } + if (!isFinite(aB)) { + throw new Error( + "$.jqplot.sprintf: (minimum-)width must be finite", + ); + } + if (!aJ) { + aJ = "fFeE".indexOf(av) > -1 ? 6 : av == "d" ? 0 : void 0; + } else { + if (aJ == "*") { + aJ = +ai[al++]; + } else { + if (aJ.charAt(0) == "*") { + aJ = +ai[aJ.slice(1, -1)]; + } else { + aJ = +aJ; + } + } + } + var aF = ax ? ai[ax.slice(0, -1)] : ai[al++]; + switch (av) { + case "s": + if (aF == null) { + return ""; + } + return ah(String(aF), aD, aB, aJ, aA, aw); + case "c": + return ah(String.fromCharCode(+aF), aD, aB, aJ, aA, aw); + case "b": + return ao(aF, 2, aL, aD, aB, aJ, aA, aw); + case "o": + return ao(aF, 8, aL, aD, aB, aJ, aA, aw); + case "x": + return ao(aF, 16, aL, aD, aB, aJ, aA, aw); + case "X": + return ao(aF, 16, aL, aD, aB, aJ, aA, aw).toUpperCase(); + case "u": + return ao(aF, 10, aL, aD, aB, aJ, aA, aw); + case "i": + var ar = parseInt(+aF, 10); + if (isNaN(ar)) { + return ""; + } + var aH = ar < 0 ? "-" : az; + var aK = au + ? ak(String(Math.abs(ar))) + : String(Math.abs(ar)); + aF = aH + an(aK, aJ, "0", false); + return aj(aF, aH, aD, aB, aA, aw); + case "d": + var ar = Math.round(+aF); + if (isNaN(ar)) { + return ""; + } + var aH = ar < 0 ? "-" : az; + var aK = au + ? ak(String(Math.abs(ar))) + : String(Math.abs(ar)); + aF = aH + an(aK, aJ, "0", false); + return aj(aF, aH, aD, aB, aA, aw); + case "e": + case "E": + case "f": + case "F": + case "g": + case "G": + var ar = +aF; + if (isNaN(ar)) { + return ""; + } + var aH = ar < 0 ? "-" : az; + var at = ["toExponential", "toFixed", "toPrecision"][ + "efg".indexOf(av.toLowerCase()) + ]; + var aN = ["toString", "toUpperCase"][ + "eEfFgG".indexOf(av) % 2 + ]; + var aK = Math.abs(ar)[at](aJ); + var aE = aK.toString().split("."); + aE[0] = au ? ak(aE[0]) : aE[0]; + aK = aE.join(L.jqplot.sprintf.decimalMark); + aF = aH + aK; + var aC = aj(aF, aH, aD, aB, aA, aw)[aN](); + return aC; + case "p": + case "P": + var ar = +aF; + if (isNaN(ar)) { + return ""; + } + var aH = ar < 0 ? "-" : az; + var aE = String( + Number(Math.abs(ar)).toExponential(), + ).split(/e|E/); + var aq = + aE[0].indexOf(".") != -1 + ? aE[0].length - 1 + : String(ar).length; + var aG = aE[1] < 0 ? -aE[1] - 1 : 0; + if (Math.abs(ar) < 1) { + if (aq + aG <= aJ) { + aF = aH + Math.abs(ar).toPrecision(aq); + } else { + if (aq <= aJ - 1) { + aF = + aH + Math.abs(ar).toExponential(aq - 1); + } else { + aF = + aH + Math.abs(ar).toExponential(aJ - 1); + } + } + } else { + var ap = aq <= aJ ? aq : aJ; + aF = aH + Math.abs(ar).toPrecision(ap); + } + var aN = ["toString", "toUpperCase"][ + "pP".indexOf(av) % 2 + ]; + return aj(aF, aH, aD, aB, aA, aw)[aN](); + case "n": + return ""; + default: + return aM; + } + }, + ); + }; + L.jqplot.sprintf.thousandsSeparator = ","; + L.jqplot.sprintf.decimalMark = "."; + L.jqplot.sprintf.regex = + /%%|%(\d+\$)?([-+#0&\' ]*)(\*\d+\$|\*|\d+)?(\.(\*\d+\$|\*|\d+))?([nAscboxXuidfegpEGP])/g; + L.jqplot.getSignificantFigures = function (al) { + var an = String(Number(Math.abs(al)).toExponential()).split(/e|E/); + var am = an[0].indexOf(".") != -1 ? an[0].length - 1 : an[0].length; + var ai = an[1] < 0 ? -an[1] - 1 : 0; + var ah = parseInt(an[1], 10); + var aj = ah + 1 > 0 ? ah + 1 : 0; + var ak = am <= aj ? 0 : am - ah - 1; + return { + significantDigits: am, + digitsLeft: aj, + digitsRight: ak, + zeros: ai, + exponent: ah, + }; + }; + L.jqplot.getPrecision = function (ah) { + return L.jqplot.getSignificantFigures(ah).digitsRight; + }; + var X = L.uiBackCompat !== false; + L.jqplot.effects = { effect: {} }; + var m = "jqplot.storage."; + L.extend(L.jqplot.effects, { + version: "1.9pre", + save: function (ai, aj) { + for (var ah = 0; ah < aj.length; ah++) { + if (aj[ah] !== null) { + ai.data(m + aj[ah], ai[0].style[aj[ah]]); + } + } + }, + restore: function (ai, aj) { + for (var ah = 0; ah < aj.length; ah++) { + if (aj[ah] !== null) { + ai.css(aj[ah], ai.data(m + aj[ah])); + } + } + }, + setMode: function (ah, ai) { + if (ai === "toggle") { + ai = ah.is(":hidden") ? "show" : "hide"; + } + return ai; + }, + createWrapper: function (ai) { + if (ai.parent().is(".ui-effects-wrapper")) { + return ai.parent(); + } + var aj = { + width: ai.outerWidth(true), + height: ai.outerHeight(true), + float: ai.css("float"), + }, + al = L("
").addClass("ui-effects-wrapper").css({ + fontSize: "100%", + background: "transparent", + border: "none", + margin: 0, + padding: 0, + }), + ah = { width: ai.width(), height: ai.height() }, + ak = document.activeElement; + ai.wrap(al); + if (ai[0] === ak || L.contains(ai[0], ak)) { + L(ak).focus(); + } + al = ai.parent(); + if (ai.css("position") === "static") { + al.css({ position: "relative" }); + ai.css({ position: "relative" }); + } else { + L.extend(aj, { + position: ai.css("position"), + zIndex: ai.css("z-index"), + }); + L.each(["top", "left", "bottom", "right"], function (am, an) { + aj[an] = ai.css(an); + if (isNaN(parseInt(aj[an], 10))) { + aj[an] = "auto"; + } + }); + ai.css({ + position: "relative", + top: 0, + left: 0, + right: "auto", + bottom: "auto", + }); + } + ai.css(ah); + return al.css(aj).show(); + }, + removeWrapper: function (ah) { + var ai = document.activeElement; + if (ah.parent().is(".ui-effects-wrapper")) { + ah.parent().replaceWith(ah); + if (ah[0] === ai || L.contains(ah[0], ai)) { + L(ai).focus(); + } + } + return ah; + }, + }); + function j(ai, ah, aj, ak) { + if (L.isPlainObject(ai)) { + return ai; + } + ai = { effect: ai }; + if (ah === u) { + ah = {}; + } + if (L.isFunction(ah)) { + ak = ah; + aj = null; + ah = {}; + } + if (L.type(ah) === "number" || L.fx.speeds[ah]) { + ak = aj; + aj = ah; + ah = {}; + } + if (L.isFunction(aj)) { + ak = aj; + aj = null; + } + if (ah) { + L.extend(ai, ah); + } + aj = aj || ah.duration; + ai.duration = L.fx.off + ? 0 + : typeof aj === "number" + ? aj + : aj in L.fx.speeds + ? L.fx.speeds[aj] + : L.fx.speeds._default; + ai.complete = ak || ah.complete; + return ai; + } + function ae(ah) { + if (!ah || typeof ah === "number" || L.fx.speeds[ah]) { + return true; + } + if (typeof ah === "string" && !L.jqplot.effects.effect[ah]) { + if (X && L.jqplot.effects[ah]) { + return false; + } + return true; + } + return false; + } + L.fn.extend({ + jqplotEffect: function (ap, aq, ai, ao) { + var an = j.apply(this, arguments), + ak = an.mode, + al = an.queue, + am = L.jqplot.effects.effect[an.effect], + ah = !am && X && L.jqplot.effects[an.effect]; + if (L.fx.off || !(am || ah)) { + if (ak) { + return this[ak](an.duration, an.complete); + } else { + return this.each(function () { + if (an.complete) { + an.complete.call(this); + } + }); + } + } + function aj(au) { + var av = L(this), + at = an.complete, + aw = an.mode; + function ar() { + if (L.isFunction(at)) { + at.call(av[0]); + } + if (L.isFunction(au)) { + au(); + } + } + if (av.is(":hidden") ? aw === "hide" : aw === "show") { + ar(); + } else { + am.call(av[0], an, ar); + } + } + if (am) { + return al === false + ? this.each(aj) + : this.queue(al || "fx", aj); + } else { + return ah.call(this, { + options: an, + duration: an.duration, + callback: an.complete, + mode: an.mode, + }); + } + }, + }); + var a = /up|down|vertical/, + v = /up|left|vertical|horizontal/; + L.jqplot.effects.effect.blind = function (aj, ao) { + var ak = L(this), + ar = [ + "position", + "top", + "bottom", + "left", + "right", + "height", + "width", + ], + ap = L.jqplot.effects.setMode(ak, aj.mode || "hide"), + au = aj.direction || "up", + am = a.test(au), + al = am ? "height" : "width", + aq = am ? "top" : "left", + aw = v.test(au), + an = {}, + av = ap === "show", + ai, + ah, + at; + if (ak.parent().is(".ui-effects-wrapper")) { + L.jqplot.effects.save(ak.parent(), ar); + } else { + L.jqplot.effects.save(ak, ar); + } + ak.show(); + at = parseInt(ak.css("top"), 10); + ai = L.jqplot.effects.createWrapper(ak).css({ overflow: "hidden" }); + ah = am ? ai[al]() + at : ai[al](); + an[al] = av ? String(ah) : "0"; + if (!aw) { + ak.css(am ? "bottom" : "right", 0) + .css(am ? "top" : "left", "") + .css({ position: "absolute" }); + an[aq] = av ? "0" : String(ah); + } + if (av) { + ai.css(al, 0); + if (!aw) { + ai.css(aq, ah); + } + } + ai.animate(an, { + duration: aj.duration, + easing: aj.easing, + queue: false, + complete: function () { + if (ap === "hide") { + ak.hide(); + } + L.jqplot.effects.restore(ak, ar); + L.jqplot.effects.removeWrapper(ak); + ao(); + }, + }); + }; +})(jQuery); diff --git a/src/adminactions/static/adminactions/js/jqplot/plugins/jqplot.barRenderer.js b/src/adminactions/static/adminactions/js/jqplot/plugins/jqplot.barRenderer.js index db8707e3..81fe1eee 100644 --- a/src/adminactions/static/adminactions/js/jqplot/plugins/jqplot.barRenderer.js +++ b/src/adminactions/static/adminactions/js/jqplot/plugins/jqplot.barRenderer.js @@ -6,13 +6,13 @@ * Revision: 1250 * * Copyright (c) 2009-2013 Chris Leonello - * jqPlot is currently available for use in all personal or commercial projects - * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL - * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can - * choose the license that best suits your project and use it accordingly. + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. * - * Although not required, the author would appreciate an email letting him - * know of any substantial use of jqPlot. You can reach the author at: + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: * chris at jqplot dot com or see http://www.jqplot.com/info.php . * * If you are feeling kind and generous, consider supporting the project by @@ -26,23 +26,22 @@ * http://hexmen.com/js/sprintf.js * The author (Ash Searle) has placed this code in the public domain: * "This code is unrestricted: you are free to use it however you like." - * + * */ -(function($) { - +(function ($) { // Class: $.jqplot.BarRenderer // A plugin renderer for jqPlot to draw a bar plot. // Draws series as a line. - - $.jqplot.BarRenderer = function(){ + + $.jqplot.BarRenderer = function () { $.jqplot.LineRenderer.call(this); }; - + $.jqplot.BarRenderer.prototype = new $.jqplot.LineRenderer(); $.jqplot.BarRenderer.prototype.constructor = $.jqplot.BarRenderer; - + // called with scope of series. - $.jqplot.BarRenderer.prototype.init = function(options, plot) { + $.jqplot.BarRenderer.prototype.init = function (options, plot) { // Group: Properties // // prop: barPadding @@ -53,16 +52,16 @@ this.barMargin = 10; // prop: barDirection // 'vertical' = up and down bars, 'horizontal' = side to side bars - this.barDirection = 'vertical'; + this.barDirection = "vertical"; // prop: barWidth // Width of the bar in pixels (auto by devaul). null = calculated automatically. this.barWidth = null; // prop: shadowOffset - // offset of the shadow from the slice and offset of + // offset of the shadow from the slice and offset of // each successive stroke of the shadow from the last. this.shadowOffset = 2; // prop: shadowDepth - // number of strokes to apply to the shadow, + // number of strokes to apply to the shadow, // each stroke offset shadowOffset from the last. this.shadowDepth = 5; // prop: shadowAlpha @@ -94,30 +93,30 @@ // an array of colors to use when highlighting a bar. this.highlightColors = []; // prop: transposedData - // NOT IMPLEMENTED YET. True if this is a horizontal bar plot and - // x and y values are "transposed". Tranposed, or "swapped", data is - // required prior to rev. 894 builds of jqPlot with horizontal bars. - // Allows backward compatability of bar renderer horizontal bars with + // NOT IMPLEMENTED YET. True if this is a horizontal bar plot and + // x and y values are "transposed". Tranposed, or "swapped", data is + // required prior to rev. 894 builds of jqPlot with horizontal bars. + // Allows backward compatability of bar renderer horizontal bars with // old style data sets. this.transposedData = true; this.renderer.animation = { show: false, - direction: 'down', + direction: "down", speed: 3000, - _supported: true + _supported: true, }; - this._type = 'bar'; - + this._type = "bar"; + // if user has passed in highlightMouseDown option and not set highlightMouseOver, disable highlightMouseOver if (options.highlightMouseDown && options.highlightMouseOver == null) { options.highlightMouseOver = false; } - + ////// // This is probably wrong here. // After going back and forth on whether renderer should be the thing // or extend the thing, it seems that it it best if it is a property - // on the thing. This should be something that is commonized + // on the thing. This should be something that is commonized // among series renderers in the future. ////// $.extend(true, this, options); @@ -129,24 +128,27 @@ this.fill = true; // if horizontal bar and animating, reset the default direction - if (this.barDirection === 'horizontal' && this.rendererOptions.animation && this.rendererOptions.animation.direction == null) { - this.renderer.animation.direction = 'left'; + if ( + this.barDirection === "horizontal" && + this.rendererOptions.animation && + this.rendererOptions.animation.direction == null + ) { + this.renderer.animation.direction = "left"; } - + if (this.waterfall) { this.fillToZero = false; this.disableStack = true; } - - if (this.barDirection == 'vertical' ) { - this._primaryAxis = '_xaxis'; - this._stackAxis = 'y'; - this.fillAxis = 'y'; - } - else { - this._primaryAxis = '_yaxis'; - this._stackAxis = 'x'; - this.fillAxis = 'x'; + + if (this.barDirection == "vertical") { + this._primaryAxis = "_xaxis"; + this._stackAxis = "y"; + this.fillAxis = "y"; + } else { + this._primaryAxis = "_yaxis"; + this._stackAxis = "x"; + this.fillAxis = "x"; } // index of the currently highlighted point, if any this._highlightedPoint = null; @@ -155,78 +157,106 @@ // Array of actual data colors used for each data point. this._dataColors = []; this._barPoints = []; - + // set the shape renderer options - var opts = {lineJoin:'miter', lineCap:'round', fill:true, isarc:false, strokeStyle:this.color, fillStyle:this.color, closePath:this.fill}; + var opts = { + lineJoin: "miter", + lineCap: "round", + fill: true, + isarc: false, + strokeStyle: this.color, + fillStyle: this.color, + closePath: this.fill, + }; this.renderer.shapeRenderer.init(opts); // set the shadow renderer options - var sopts = {lineJoin:'miter', lineCap:'round', fill:true, isarc:false, angle:this.shadowAngle, offset:this.shadowOffset, alpha:this.shadowAlpha, depth:this.shadowDepth, closePath:this.fill}; + var sopts = { + lineJoin: "miter", + lineCap: "round", + fill: true, + isarc: false, + angle: this.shadowAngle, + offset: this.shadowOffset, + alpha: this.shadowAlpha, + depth: this.shadowDepth, + closePath: this.fill, + }; this.renderer.shadowRenderer.init(sopts); - + plot.postInitHooks.addOnce(postInit); plot.postDrawHooks.addOnce(postPlotDraw); - plot.eventListenerHooks.addOnce('jqplotMouseMove', handleMove); - plot.eventListenerHooks.addOnce('jqplotMouseDown', handleMouseDown); - plot.eventListenerHooks.addOnce('jqplotMouseUp', handleMouseUp); - plot.eventListenerHooks.addOnce('jqplotClick', handleClick); - plot.eventListenerHooks.addOnce('jqplotRightClick', handleRightClick); + plot.eventListenerHooks.addOnce("jqplotMouseMove", handleMove); + plot.eventListenerHooks.addOnce("jqplotMouseDown", handleMouseDown); + plot.eventListenerHooks.addOnce("jqplotMouseUp", handleMouseUp); + plot.eventListenerHooks.addOnce("jqplotClick", handleClick); + plot.eventListenerHooks.addOnce("jqplotRightClick", handleRightClick); }; - + // called with scope of series function barPreInit(target, data, seriesDefaults, options) { - if (this.rendererOptions.barDirection == 'horizontal') { - this._stackAxis = 'x'; - this._primaryAxis = '_yaxis'; + if (this.rendererOptions.barDirection == "horizontal") { + this._stackAxis = "x"; + this._primaryAxis = "_yaxis"; } if (this.rendererOptions.waterfall == true) { this._data = $.extend(true, [], this.data); var sum = 0; - var pos = (!this.rendererOptions.barDirection || this.rendererOptions.barDirection === 'vertical' || this.transposedData === false) ? 1 : 0; - for(var i=0; i0) { - this.data[i][pos] += this.data[i-1][pos]; + if (i > 0) { + this.data[i][pos] += this.data[i - 1][pos]; } } - this.data[this.data.length] = (pos == 1) ? [this.data.length+1, sum] : [sum, this.data.length+1]; - this._data[this._data.length] = (pos == 1) ? [this._data.length+1, sum] : [sum, this._data.length+1]; + this.data[this.data.length] = + pos == 1 + ? [this.data.length + 1, sum] + : [sum, this.data.length + 1]; + this._data[this._data.length] = + pos == 1 + ? [this._data.length + 1, sum] + : [sum, this._data.length + 1]; } if (this.rendererOptions.groups > 1) { this.breakOnNull = true; var l = this.data.length; - var skip = parseInt(l/this.rendererOptions.groups, 10); + var skip = parseInt(l / this.rendererOptions.groups, 10); var count = 0; - for (var i=skip; i 570) ? newrgb[j] * 0.8 : newrgb[j] + 0.3 * (255 - newrgb[j]); + newrgb[j] = + sum > 570 + ? newrgb[j] * 0.8 + : newrgb[j] + 0.3 * (255 - newrgb[j]); newrgb[j] = parseInt(newrgb[j], 10); } - ret.push('rgb('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+')'); + ret.push( + "rgb(" + newrgb[0] + "," + newrgb[1] + "," + newrgb[2] + ")", + ); } return ret; } @@ -298,14 +345,14 @@ prevSeriesIndex = sidx - 1, start, prevVal, - aidx = (axis === 'x') ? 0 : 1; + aidx = axis === "x" ? 0 : 1; // is this not the first series? if (seriesIndex > 0) { prevVal = plot.series[prevSeriesIndex]._plotData[didx][aidx]; // is there a sign change - if ((comp * prevVal) < 0) { + if (comp * prevVal < 0) { start = getStart(prevSeriesIndex, didx, comp, plot, axis); } @@ -313,26 +360,32 @@ else { start = plot.series[prevSeriesIndex].gridData[didx][aidx]; } - } // if first series, return value at 0 else { - - start = (aidx === 0) ? plot.series[seriesIndex]._xaxis.series_u2p(0) : plot.series[seriesIndex]._yaxis.series_u2p(0); + start = + aidx === 0 + ? plot.series[seriesIndex]._xaxis.series_u2p(0) + : plot.series[seriesIndex]._yaxis.series_u2p(0); } return start; } - - $.jqplot.BarRenderer.prototype.draw = function(ctx, gridData, options, plot) { + $.jqplot.BarRenderer.prototype.draw = function ( + ctx, + gridData, + options, + plot, + ) { var i; // Ughhh, have to make a copy of options b/c it may be modified later. var opts = $.extend({}, options); - var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow; - var showLine = (opts.showLine != undefined) ? opts.showLine : this.showLine; - var fill = (opts.fill != undefined) ? opts.fill : this.fill; + var shadow = opts.shadow != undefined ? opts.shadow : this.shadow; + var showLine = + opts.showLine != undefined ? opts.showLine : this.showLine; + var fill = opts.fill != undefined ? opts.fill : this.fill; var xaxis = this.xaxis; var yaxis = this.yaxis; var xp = this._xaxis.series_u2p; @@ -341,116 +394,128 @@ // clear out data colors. this._dataColors = []; this._barPoints = []; - + if (this.barWidth == null) { this.renderer.setBarWidth.call(this); } - - var temp = this._plotSeriesInfo = this.renderer.calcSeriesNumbers.call(this); + + var temp = (this._plotSeriesInfo = + this.renderer.calcSeriesNumbers.call(this)); var nvals = temp[0]; var nseries = temp[1]; var pos = temp[2]; var points = []; - + if (this._stack) { this._barNudge = 0; - } - else { - this._barNudge = (-Math.abs(nseries/2 - 0.5) + pos) * (this.barWidth + this.barPadding); + } else { + this._barNudge = + (-Math.abs(nseries / 2 - 0.5) + pos) * + (this.barWidth + this.barPadding); } if (showLine) { - var negativeColors = new $.jqplot.ColorGenerator(this.negativeSeriesColors); + var negativeColors = new $.jqplot.ColorGenerator( + this.negativeSeriesColors, + ); var positiveColors = new $.jqplot.ColorGenerator(this.seriesColors); var negativeColor = negativeColors.get(this.index); - if (! this.useNegativeColors) { + if (!this.useNegativeColors) { negativeColor = opts.fillStyle; } var positiveColor = opts.fillStyle; var base; - var xstart; + var xstart; var ystart; - - if (this.barDirection == 'vertical') { - for (var i=0; i 0 && i < this.gridData.length-1) { - ystart = this.gridData[i-1][1]; - } - else if (this.waterfall && i == 0 && i < this.gridData.length-1) { + } else if ( + this.waterfall && + i > 0 && + i < this.gridData.length - 1 + ) { + ystart = this.gridData[i - 1][1]; + } else if ( + this.waterfall && + i == 0 && + i < this.gridData.length - 1 + ) { if (this._yaxis.min <= 0 && this._yaxis.max >= 0) { ystart = this._yaxis.series_u2p(0); - } - else if (this._yaxis.min > 0) { + } else if (this._yaxis.min > 0) { ystart = ctx.canvas.height; - } - else { + } else { ystart = 0; } - } - else if (this.waterfall && i == this.gridData.length - 1) { + } else if ( + this.waterfall && + i == this.gridData.length - 1 + ) { if (this._yaxis.min <= 0 && this._yaxis.max >= 0) { ystart = this._yaxis.series_u2p(0); - } - else if (this._yaxis.min > 0) { + } else if (this._yaxis.min > 0) { ystart = ctx.canvas.height; - } - else { + } else { ystart = 0; } - } - else { + } else { ystart = ctx.canvas.height; } } - if ((this.fillToZero && this._plotData[i][1] < 0) || (this.waterfall && this._data[i][1] < 0)) { + if ( + (this.fillToZero && this._plotData[i][1] < 0) || + (this.waterfall && this._data[i][1] < 0) + ) { if (this.varyBarColor && !this._stack) { if (this.useNegativeColors) { opts.fillStyle = negativeColors.next(); - } - else { + } else { opts.fillStyle = positiveColors.next(); } - } - else { + } else { opts.fillStyle = negativeColor; } - } - else { + } else { if (this.varyBarColor && !this._stack) { opts.fillStyle = positiveColors.next(); - } - else { + } else { opts.fillStyle = positiveColor; } } - - if (!this.fillToZero || this._plotData[i][1] >= 0) { - points.push([base-this.barWidth/2, ystart]); - points.push([base-this.barWidth/2, gridData[i][1]]); - points.push([base+this.barWidth/2, gridData[i][1]]); - points.push([base+this.barWidth/2, ystart]); + + if (!this.fillToZero || this._plotData[i][1] >= 0) { + points.push([base - this.barWidth / 2, ystart]); + points.push([base - this.barWidth / 2, gridData[i][1]]); + points.push([base + this.barWidth / 2, gridData[i][1]]); + points.push([base + this.barWidth / 2, ystart]); } // for negative bars make sure points are always ordered clockwise - else { - points.push([base-this.barWidth/2, gridData[i][1]]); - points.push([base-this.barWidth/2, ystart]); - points.push([base+this.barWidth/2, ystart]); - points.push([base+this.barWidth/2, gridData[i][1]]); + else { + points.push([base - this.barWidth / 2, gridData[i][1]]); + points.push([base - this.barWidth / 2, ystart]); + points.push([base + this.barWidth / 2, ystart]); + points.push([base + this.barWidth / 2, gridData[i][1]]); } this._barPoints.push(points); // now draw the shadows if not stacked. @@ -463,86 +528,90 @@ } var clr = opts.fillStyle || this.color; this._dataColors.push(clr); - this.renderer.shapeRenderer.draw(ctx, points, opts); + this.renderer.shapeRenderer.draw(ctx, points, opts); } - } - - else if (this.barDirection == 'horizontal'){ - for (var i=0; i 0 && i < this.gridData.length-1) { - xstart = this.gridData[i-1][0]; - } - else if (this.waterfall && i == 0 && i < this.gridData.length-1) { + } else if ( + this.waterfall && + i > 0 && + i < this.gridData.length - 1 + ) { + xstart = this.gridData[i - 1][0]; + } else if ( + this.waterfall && + i == 0 && + i < this.gridData.length - 1 + ) { if (this._xaxis.min <= 0 && this._xaxis.max >= 0) { xstart = this._xaxis.series_u2p(0); - } - else if (this._xaxis.min > 0) { + } else if (this._xaxis.min > 0) { xstart = 0; - } - else { + } else { xstart = 0; } - } - else if (this.waterfall && i == this.gridData.length - 1) { + } else if ( + this.waterfall && + i == this.gridData.length - 1 + ) { if (this._xaxis.min <= 0 && this._xaxis.max >= 0) { xstart = this._xaxis.series_u2p(0); - } - else if (this._xaxis.min > 0) { + } else if (this._xaxis.min > 0) { xstart = 0; - } - else { + } else { xstart = ctx.canvas.width; } - } - else { + } else { xstart = 0; } } - if ((this.fillToZero && this._plotData[i][0] < 0) || (this.waterfall && this._data[i][0] < 0)) { + if ( + (this.fillToZero && this._plotData[i][0] < 0) || + (this.waterfall && this._data[i][0] < 0) + ) { if (this.varyBarColor && !this._stack) { if (this.useNegativeColors) { opts.fillStyle = negativeColors.next(); - } - else { + } else { opts.fillStyle = positiveColors.next(); } - } - else { + } else { opts.fillStyle = negativeColor; } - } - else { + } else { if (this.varyBarColor && !this._stack) { opts.fillStyle = positiveColors.next(); - } - else { + } else { opts.fillStyle = positiveColor; - } + } } - if (!this.fillToZero || this._plotData[i][0] >= 0) { points.push([xstart, base + this.barWidth / 2]); points.push([xstart, base - this.barWidth / 2]); points.push([gridData[i][0], base - this.barWidth / 2]); points.push([gridData[i][0], base + this.barWidth / 2]); - } - else { + } else { points.push([gridData[i][0], base + this.barWidth / 2]); points.push([gridData[i][0], base - this.barWidth / 2]); points.push([xstart, base - this.barWidth / 2]); @@ -560,120 +629,130 @@ var clr = opts.fillStyle || this.color; this._dataColors.push(clr); this.renderer.shapeRenderer.draw(ctx, points, opts); - } + } } - } - - if (this.highlightColors.length == 0) { - this.highlightColors = $.jqplot.computeHighlightColors(this._dataColors); } - - else if (typeof(this.highlightColors) == 'string') { + + if (this.highlightColors.length == 0) { + this.highlightColors = $.jqplot.computeHighlightColors( + this._dataColors, + ); + } else if (typeof this.highlightColors == "string") { var temp = this.highlightColors; this.highlightColors = []; - for (var i=0; i0){this.data[q][u]+=this.data[q-1][u]}}this.data[this.data.length]=(u==1)?[this.data.length+1,s]:[s,this.data.length+1];this._data[this._data.length]=(u==1)?[this._data.length+1,s]:[s,this._data.length+1]}if(this.rendererOptions.groups>1){this.breakOnNull=true;var n=this.data.length;var v=parseInt(n/this.rendererOptions.groups,10);var r=0;for(var q=v;q570)?n[p]*0.8:n[p]+0.3*(255-n[p]);n[p]=parseInt(n[p],10)}q.push("rgb("+n[0]+","+n[1]+","+n[2]+")")}return q}function i(v,u,s,t,o){var q=v,w=v-1,n,p,r=(o==="x")?0:1;if(q>0){p=t.series[w]._plotData[u][r];if((s*p)<0){n=i(w,u,s,t,o)}else{n=t.series[w].gridData[u][r]}}else{n=(r===0)?t.series[q]._xaxis.series_u2p(0):t.series[q]._yaxis.series_u2p(0)}return n}d.jqplot.BarRenderer.prototype.draw=function(E,L,q,G){var I;var A=d.extend({},q);var w=(A.shadow!=undefined)?A.shadow:this.shadow;var O=(A.showLine!=undefined)?A.showLine:this.showLine;var F=(A.fill!=undefined)?A.fill:this.fill;var p=this.xaxis;var J=this.yaxis;var y=this._xaxis.series_u2p;var K=this._yaxis.series_u2p;var D,C;this._dataColors=[];this._barPoints=[];if(this.barWidth==null){this.renderer.setBarWidth.call(this)}var N=this._plotSeriesInfo=this.renderer.calcSeriesNumbers.call(this);var x=N[0];var v=N[1];var s=N[2];var H=[];if(this._stack){this._barNudge=0}else{this._barNudge=(-Math.abs(v/2-0.5)+s)*(this.barWidth+this.barPadding)}if(O){var u=new d.jqplot.ColorGenerator(this.negativeSeriesColors);var B=new d.jqplot.ColorGenerator(this.seriesColors);var M=u.get(this.index);if(!this.useNegativeColors){M=A.fillStyle}var t=A.fillStyle;var r;var P;var o;if(this.barDirection=="vertical"){for(var I=0;I0&&I=0){o=this._yaxis.series_u2p(0)}else{if(this._yaxis.min>0){o=E.canvas.height}else{o=0}}}else{if(this.waterfall&&I==this.gridData.length-1){if(this._yaxis.min<=0&&this._yaxis.max>=0){o=this._yaxis.series_u2p(0)}else{if(this._yaxis.min>0){o=E.canvas.height}else{o=0}}}else{o=E.canvas.height}}}}}if((this.fillToZero&&this._plotData[I][1]<0)||(this.waterfall&&this._data[I][1]<0)){if(this.varyBarColor&&!this._stack){if(this.useNegativeColors){A.fillStyle=u.next()}else{A.fillStyle=B.next()}}else{A.fillStyle=M}}else{if(this.varyBarColor&&!this._stack){A.fillStyle=B.next()}else{A.fillStyle=t}}if(!this.fillToZero||this._plotData[I][1]>=0){H.push([r-this.barWidth/2,o]);H.push([r-this.barWidth/2,L[I][1]]);H.push([r+this.barWidth/2,L[I][1]]);H.push([r+this.barWidth/2,o])}else{H.push([r-this.barWidth/2,L[I][1]]);H.push([r-this.barWidth/2,o]);H.push([r+this.barWidth/2,o]);H.push([r+this.barWidth/2,L[I][1]])}this._barPoints.push(H);if(w&&!this._stack){var z=d.extend(true,{},A);delete z.fillStyle;this.renderer.shadowRenderer.draw(E,H,z)}var n=A.fillStyle||this.color;this._dataColors.push(n);this.renderer.shapeRenderer.draw(E,H,A)}}else{if(this.barDirection=="horizontal"){for(var I=0;I0&&I=0){P=this._xaxis.series_u2p(0)}else{if(this._xaxis.min>0){P=0}else{P=0}}}else{if(this.waterfall&&I==this.gridData.length-1){if(this._xaxis.min<=0&&this._xaxis.max>=0){P=this._xaxis.series_u2p(0)}else{if(this._xaxis.min>0){P=0}else{P=E.canvas.width}}}else{P=0}}}}}if((this.fillToZero&&this._plotData[I][0]<0)||(this.waterfall&&this._data[I][0]<0)){if(this.varyBarColor&&!this._stack){if(this.useNegativeColors){A.fillStyle=u.next()}else{A.fillStyle=B.next()}}else{A.fillStyle=M}}else{if(this.varyBarColor&&!this._stack){A.fillStyle=B.next()}else{A.fillStyle=t}}if(!this.fillToZero||this._plotData[I][0]>=0){H.push([P,r+this.barWidth/2]);H.push([P,r-this.barWidth/2]);H.push([L[I][0],r-this.barWidth/2]);H.push([L[I][0],r+this.barWidth/2])}else{H.push([L[I][0],r+this.barWidth/2]);H.push([L[I][0],r-this.barWidth/2]);H.push([P,r-this.barWidth/2]);H.push([P,r+this.barWidth/2])}this._barPoints.push(H);if(w&&!this._stack){var z=d.extend(true,{},A);delete z.fillStyle;this.renderer.shadowRenderer.draw(E,H,z)}var n=A.fillStyle||this.color;this._dataColors.push(n);this.renderer.shapeRenderer.draw(E,H,A)}}}}if(this.highlightColors.length==0){this.highlightColors=d.jqplot.computeHighlightColors(this._dataColors)}else{if(typeof(this.highlightColors)=="string"){var N=this.highlightColors;this.highlightColors=[];for(var I=0;I 0) { + this.data[q][u] += this.data[q - 1][u]; + } + } + this.data[this.data.length] = + u == 1 ? [this.data.length + 1, s] : [s, this.data.length + 1]; + this._data[this._data.length] = + u == 1 + ? [this._data.length + 1, s] + : [s, this._data.length + 1]; + } + if (this.rendererOptions.groups > 1) { + this.breakOnNull = true; + var n = this.data.length; + var v = parseInt(n / this.rendererOptions.groups, 10); + var r = 0; + for (var q = v; q < n; q += v) { + this.data.splice(q + r, 0, [null, null]); + this._plotData.splice(q + r, 0, [null, null]); + this._stackData.splice(q + r, 0, [null, null]); + r++; + } + for (q = 0; q < this.data.length; q++) { + if (this._primaryAxis == "_xaxis") { + this.data[q][0] = q + 1; + this._plotData[q][0] = q + 1; + this._stackData[q][0] = q + 1; + } else { + this.data[q][1] = q + 1; + this._plotData[q][1] = q + 1; + this._stackData[q][1] = q + 1; + } + } + } + } + d.jqplot.preSeriesInitHooks.push(g); + d.jqplot.BarRenderer.prototype.calcSeriesNumbers = function () { + var r = 0; + var t = 0; + var q = this[this._primaryAxis]; + var p, o, u; + for (var n = 0; n < q._series.length; n++) { + o = q._series[n]; + if (o === this) { + u = n; + } + if (o.renderer.constructor == d.jqplot.BarRenderer) { + r += o.data.length; + t += 1; + } + } + return [r, t, u]; + }; + d.jqplot.BarRenderer.prototype.setBarWidth = function () { + var q; + var n = 0; + var o = 0; + var t = this[this._primaryAxis]; + var x, r, v; + var w = (this._plotSeriesInfo = + this.renderer.calcSeriesNumbers.call(this)); + n = w[0]; + o = w[1]; + var u = t.numberTicks; + var p = (u - 1) / 2; + if (t.name == "xaxis" || t.name == "x2axis") { + if (this._stack) { + this.barWidth = + ((t._offsets.max - t._offsets.min) / n) * o - + this.barMargin; + } else { + this.barWidth = + ((t._offsets.max - t._offsets.min) / p - + this.barPadding * (o - 1) - + this.barMargin * 2) / + o; + } + } else { + if (this._stack) { + this.barWidth = + ((t._offsets.min - t._offsets.max) / n) * o - + this.barMargin; + } else { + this.barWidth = + ((t._offsets.min - t._offsets.max) / p - + this.barPadding * (o - 1) - + this.barMargin * 2) / + o; + } + } + return [n, o]; + }; + function f(o) { + var q = []; + for (var s = 0; s < o.length; s++) { + var r = d.jqplot.getColorComponents(o[s]); + var n = [r[0], r[1], r[2]]; + var t = n[0] + n[1] + n[2]; + for (var p = 0; p < 3; p++) { + n[p] = t > 570 ? n[p] * 0.8 : n[p] + 0.3 * (255 - n[p]); + n[p] = parseInt(n[p], 10); + } + q.push("rgb(" + n[0] + "," + n[1] + "," + n[2] + ")"); + } + return q; + } + function i(v, u, s, t, o) { + var q = v, + w = v - 1, + n, + p, + r = o === "x" ? 0 : 1; + if (q > 0) { + p = t.series[w]._plotData[u][r]; + if (s * p < 0) { + n = i(w, u, s, t, o); + } else { + n = t.series[w].gridData[u][r]; + } + } else { + n = + r === 0 + ? t.series[q]._xaxis.series_u2p(0) + : t.series[q]._yaxis.series_u2p(0); + } + return n; + } + d.jqplot.BarRenderer.prototype.draw = function (E, L, q, G) { + var I; + var A = d.extend({}, q); + var w = A.shadow != undefined ? A.shadow : this.shadow; + var O = A.showLine != undefined ? A.showLine : this.showLine; + var F = A.fill != undefined ? A.fill : this.fill; + var p = this.xaxis; + var J = this.yaxis; + var y = this._xaxis.series_u2p; + var K = this._yaxis.series_u2p; + var D, C; + this._dataColors = []; + this._barPoints = []; + if (this.barWidth == null) { + this.renderer.setBarWidth.call(this); + } + var N = (this._plotSeriesInfo = + this.renderer.calcSeriesNumbers.call(this)); + var x = N[0]; + var v = N[1]; + var s = N[2]; + var H = []; + if (this._stack) { + this._barNudge = 0; + } else { + this._barNudge = + (-Math.abs(v / 2 - 0.5) + s) * + (this.barWidth + this.barPadding); + } + if (O) { + var u = new d.jqplot.ColorGenerator(this.negativeSeriesColors); + var B = new d.jqplot.ColorGenerator(this.seriesColors); + var M = u.get(this.index); + if (!this.useNegativeColors) { + M = A.fillStyle; + } + var t = A.fillStyle; + var r; + var P; + var o; + if (this.barDirection == "vertical") { + for (var I = 0; I < L.length; I++) { + if (!this._stack && this.data[I][1] == null) { + continue; + } + H = []; + r = L[I][0] + this._barNudge; + if (this._stack && this._prevGridData.length) { + o = i(this.index, I, this._plotData[I][1], G, "y"); + } else { + if (this.fillToZero) { + o = this._yaxis.series_u2p(0); + } else { + if ( + this.waterfall && + I > 0 && + I < this.gridData.length - 1 + ) { + o = this.gridData[I - 1][1]; + } else { + if ( + this.waterfall && + I == 0 && + I < this.gridData.length - 1 + ) { + if ( + this._yaxis.min <= 0 && + this._yaxis.max >= 0 + ) { + o = this._yaxis.series_u2p(0); + } else { + if (this._yaxis.min > 0) { + o = E.canvas.height; + } else { + o = 0; + } + } + } else { + if ( + this.waterfall && + I == this.gridData.length - 1 + ) { + if ( + this._yaxis.min <= 0 && + this._yaxis.max >= 0 + ) { + o = this._yaxis.series_u2p(0); + } else { + if (this._yaxis.min > 0) { + o = E.canvas.height; + } else { + o = 0; + } + } + } else { + o = E.canvas.height; + } + } + } + } + } + if ( + (this.fillToZero && this._plotData[I][1] < 0) || + (this.waterfall && this._data[I][1] < 0) + ) { + if (this.varyBarColor && !this._stack) { + if (this.useNegativeColors) { + A.fillStyle = u.next(); + } else { + A.fillStyle = B.next(); + } + } else { + A.fillStyle = M; + } + } else { + if (this.varyBarColor && !this._stack) { + A.fillStyle = B.next(); + } else { + A.fillStyle = t; + } + } + if (!this.fillToZero || this._plotData[I][1] >= 0) { + H.push([r - this.barWidth / 2, o]); + H.push([r - this.barWidth / 2, L[I][1]]); + H.push([r + this.barWidth / 2, L[I][1]]); + H.push([r + this.barWidth / 2, o]); + } else { + H.push([r - this.barWidth / 2, L[I][1]]); + H.push([r - this.barWidth / 2, o]); + H.push([r + this.barWidth / 2, o]); + H.push([r + this.barWidth / 2, L[I][1]]); + } + this._barPoints.push(H); + if (w && !this._stack) { + var z = d.extend(true, {}, A); + delete z.fillStyle; + this.renderer.shadowRenderer.draw(E, H, z); + } + var n = A.fillStyle || this.color; + this._dataColors.push(n); + this.renderer.shapeRenderer.draw(E, H, A); + } + } else { + if (this.barDirection == "horizontal") { + for (var I = 0; I < L.length; I++) { + if (!this._stack && this.data[I][0] == null) { + continue; + } + H = []; + r = L[I][1] - this._barNudge; + P; + if (this._stack && this._prevGridData.length) { + P = i(this.index, I, this._plotData[I][0], G, "x"); + } else { + if (this.fillToZero) { + P = this._xaxis.series_u2p(0); + } else { + if ( + this.waterfall && + I > 0 && + I < this.gridData.length - 1 + ) { + P = this.gridData[I - 1][0]; + } else { + if ( + this.waterfall && + I == 0 && + I < this.gridData.length - 1 + ) { + if ( + this._xaxis.min <= 0 && + this._xaxis.max >= 0 + ) { + P = this._xaxis.series_u2p(0); + } else { + if (this._xaxis.min > 0) { + P = 0; + } else { + P = 0; + } + } + } else { + if ( + this.waterfall && + I == this.gridData.length - 1 + ) { + if ( + this._xaxis.min <= 0 && + this._xaxis.max >= 0 + ) { + P = this._xaxis.series_u2p(0); + } else { + if (this._xaxis.min > 0) { + P = 0; + } else { + P = E.canvas.width; + } + } + } else { + P = 0; + } + } + } + } + } + if ( + (this.fillToZero && this._plotData[I][0] < 0) || + (this.waterfall && this._data[I][0] < 0) + ) { + if (this.varyBarColor && !this._stack) { + if (this.useNegativeColors) { + A.fillStyle = u.next(); + } else { + A.fillStyle = B.next(); + } + } else { + A.fillStyle = M; + } + } else { + if (this.varyBarColor && !this._stack) { + A.fillStyle = B.next(); + } else { + A.fillStyle = t; + } + } + if (!this.fillToZero || this._plotData[I][0] >= 0) { + H.push([P, r + this.barWidth / 2]); + H.push([P, r - this.barWidth / 2]); + H.push([L[I][0], r - this.barWidth / 2]); + H.push([L[I][0], r + this.barWidth / 2]); + } else { + H.push([L[I][0], r + this.barWidth / 2]); + H.push([L[I][0], r - this.barWidth / 2]); + H.push([P, r - this.barWidth / 2]); + H.push([P, r + this.barWidth / 2]); + } + this._barPoints.push(H); + if (w && !this._stack) { + var z = d.extend(true, {}, A); + delete z.fillStyle; + this.renderer.shadowRenderer.draw(E, H, z); + } + var n = A.fillStyle || this.color; + this._dataColors.push(n); + this.renderer.shapeRenderer.draw(E, H, A); + } + } + } + } + if (this.highlightColors.length == 0) { + this.highlightColors = d.jqplot.computeHighlightColors( + this._dataColors, + ); + } else { + if (typeof this.highlightColors == "string") { + var N = this.highlightColors; + this.highlightColors = []; + for (var I = 0; I < this._dataColors.length; I++) { + this.highlightColors.push(N); + } + } + } + }; + d.jqplot.BarRenderer.prototype.drawShadow = function (z, G, p, B) { + var D; + var w = p != undefined ? p : {}; + var t = w.shadow != undefined ? w.shadow : this.shadow; + var I = w.showLine != undefined ? w.showLine : this.showLine; + var A = w.fill != undefined ? w.fill : this.fill; + var o = this.xaxis; + var E = this.yaxis; + var v = this._xaxis.series_u2p; + var F = this._yaxis.series_u2p; + var y, C, x, u, s, r; + if (this._stack && this.shadow) { + if (this.barWidth == null) { + this.renderer.setBarWidth.call(this); + } + var H = (this._plotSeriesInfo = + this.renderer.calcSeriesNumbers.call(this)); + u = H[0]; + s = H[1]; + r = H[2]; + if (this._stack) { + this._barNudge = 0; + } else { + this._barNudge = + (-Math.abs(s / 2 - 0.5) + r) * + (this.barWidth + this.barPadding); + } + if (I) { + if (this.barDirection == "vertical") { + for (var D = 0; D < G.length; D++) { + if (this.data[D][1] == null) { + continue; + } + C = []; + var q = G[D][0] + this._barNudge; + var n; + if (this._stack && this._prevGridData.length) { + n = i(this.index, D, this._plotData[D][1], B, "y"); + } else { + if (this.fillToZero) { + n = this._yaxis.series_u2p(0); + } else { + n = z.canvas.height; + } + } + C.push([q - this.barWidth / 2, n]); + C.push([q - this.barWidth / 2, G[D][1]]); + C.push([q + this.barWidth / 2, G[D][1]]); + C.push([q + this.barWidth / 2, n]); + this.renderer.shadowRenderer.draw(z, C, w); + } + } else { + if (this.barDirection == "horizontal") { + for (var D = 0; D < G.length; D++) { + if (this.data[D][0] == null) { + continue; + } + C = []; + var q = G[D][1] - this._barNudge; + var J; + if (this._stack && this._prevGridData.length) { + J = i( + this.index, + D, + this._plotData[D][0], + B, + "x", + ); + } else { + if (this.fillToZero) { + J = this._xaxis.series_u2p(0); + } else { + J = 0; + } + } + C.push([J, q + this.barWidth / 2]); + C.push([G[D][0], q + this.barWidth / 2]); + C.push([G[D][0], q - this.barWidth / 2]); + C.push([J, q - this.barWidth / 2]); + this.renderer.shadowRenderer.draw(z, C, w); + } + } + } + } + } + }; + function h(q, p, n) { + for (var o = 0; o < this.series.length; o++) { + if (this.series[o].renderer.constructor == d.jqplot.BarRenderer) { + if (this.series[o].highlightMouseOver) { + this.series[o].highlightMouseDown = false; + } + } + } + } + function j() { + if ( + this.plugins.barRenderer && + this.plugins.barRenderer.highlightCanvas + ) { + this.plugins.barRenderer.highlightCanvas.resetCanvas(); + this.plugins.barRenderer.highlightCanvas = null; + } + this.plugins.barRenderer = { highlightedSeriesIndex: null }; + this.plugins.barRenderer.highlightCanvas = new d.jqplot.GenericCanvas(); + this.eventCanvas._elem.before( + this.plugins.barRenderer.highlightCanvas.createElement( + this._gridPadding, + "jqplot-barRenderer-highlight-canvas", + this._plotDimensions, + this, + ), + ); + this.plugins.barRenderer.highlightCanvas.setContext(); + this.eventCanvas._elem.bind("mouseleave", { plot: this }, function (n) { + k(n.data.plot); + }); + } + function c(u, t, q, p) { + var o = u.series[t]; + var n = u.plugins.barRenderer.highlightCanvas; + n._ctx.clearRect(0, 0, n._ctx.canvas.width, n._ctx.canvas.height); + o._highlightedPoint = q; + u.plugins.barRenderer.highlightedSeriesIndex = t; + var r = { fillStyle: o.highlightColors[q] }; + o.renderer.shapeRenderer.draw(n._ctx, p, r); + n = null; + } + function k(p) { + var n = p.plugins.barRenderer.highlightCanvas; + n._ctx.clearRect(0, 0, n._ctx.canvas.width, n._ctx.canvas.height); + for (var o = 0; o < p.series.length; o++) { + p.series[o]._highlightedPoint = null; + } + p.plugins.barRenderer.highlightedSeriesIndex = null; + p.target.trigger("jqplotDataUnhighlight"); + n = null; + } + function b(r, q, u, t, s) { + if (t) { + var p = [t.seriesIndex, t.pointIndex, t.data]; + var o = jQuery.Event("jqplotDataMouseOver"); + o.pageX = r.pageX; + o.pageY = r.pageY; + s.target.trigger(o, p); + if ( + s.series[p[0]].show && + s.series[p[0]].highlightMouseOver && + !( + p[0] == s.plugins.barRenderer.highlightedSeriesIndex && + p[1] == s.series[p[0]]._highlightedPoint + ) + ) { + var n = jQuery.Event("jqplotDataHighlight"); + n.which = r.which; + n.pageX = r.pageX; + n.pageY = r.pageY; + s.target.trigger(n, p); + c(s, t.seriesIndex, t.pointIndex, t.points); + } + } else { + if (t == null) { + k(s); + } + } + } + function a(q, p, t, s, r) { + if (s) { + var o = [s.seriesIndex, s.pointIndex, s.data]; + if ( + r.series[o[0]].highlightMouseDown && + !( + o[0] == r.plugins.barRenderer.highlightedSeriesIndex && + o[1] == r.series[o[0]]._highlightedPoint + ) + ) { + var n = jQuery.Event("jqplotDataHighlight"); + n.which = q.which; + n.pageX = q.pageX; + n.pageY = q.pageY; + r.target.trigger(n, o); + c(r, s.seriesIndex, s.pointIndex, s.points); + } + } else { + if (s == null) { + k(r); + } + } + } + function l(p, o, s, r, q) { + var n = q.plugins.barRenderer.highlightedSeriesIndex; + if (n != null && q.series[n].highlightMouseDown) { + k(q); + } + } + function e(q, p, t, s, r) { + if (s) { + var o = [s.seriesIndex, s.pointIndex, s.data]; + var n = jQuery.Event("jqplotDataClick"); + n.which = q.which; + n.pageX = q.pageX; + n.pageY = q.pageY; + r.target.trigger(n, o); + } + } + function m(r, q, u, t, s) { + if (t) { + var p = [t.seriesIndex, t.pointIndex, t.data]; + var n = s.plugins.barRenderer.highlightedSeriesIndex; + if (n != null && s.series[n].highlightMouseDown) { + k(s); + } + var o = jQuery.Event("jqplotDataRightClick"); + o.which = r.which; + o.pageX = r.pageX; + o.pageY = r.pageY; + s.target.trigger(o, p); + } + } +})(jQuery); diff --git a/src/adminactions/static/adminactions/js/jqplot/plugins/jqplot.categoryAxisRenderer.js b/src/adminactions/static/adminactions/js/jqplot/plugins/jqplot.categoryAxisRenderer.js index 8b0968b1..e0c21947 100644 --- a/src/adminactions/static/adminactions/js/jqplot/plugins/jqplot.categoryAxisRenderer.js +++ b/src/adminactions/static/adminactions/js/jqplot/plugins/jqplot.categoryAxisRenderer.js @@ -6,13 +6,13 @@ * Revision: 1250 * * Copyright (c) 2009-2013 Chris Leonello - * jqPlot is currently available for use in all personal or commercial projects - * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL - * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can - * choose the license that best suits your project and use it accordingly. + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. * - * Although not required, the author would appreciate an email letting him - * know of any substantial use of jqPlot. You can reach the author at: + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: * chris at jqplot dot com or see http://www.jqplot.com/info.php . * * If you are feeling kind and generous, consider supporting the project by @@ -26,21 +26,21 @@ * http://hexmen.com/js/sprintf.js * The author (Ash Searle) has placed this code in the public domain: * "This code is unrestricted: you are free to use it however you like." - * + * */ -(function($) { +(function ($) { /** - * class: $.jqplot.CategoryAxisRenderer - * A plugin for jqPlot to render a category style axis, with equal pixel spacing between y data values of a series. - * - * To use this renderer, include the plugin in your source - * > - * - * and supply the appropriate options to your plot - * - * > {axes:{xaxis:{renderer:$.jqplot.CategoryAxisRenderer}}} - **/ - $.jqplot.CategoryAxisRenderer = function(options) { + * class: $.jqplot.CategoryAxisRenderer + * A plugin for jqPlot to render a category style axis, with equal pixel spacing between y data values of a series. + * + * To use this renderer, include the plugin in your source + * > + * + * and supply the appropriate options to your plot + * + * > {axes:{xaxis:{renderer:$.jqplot.CategoryAxisRenderer}}} + **/ + $.jqplot.CategoryAxisRenderer = function (options) { $.jqplot.LinearAxisRenderer.call(this); // prop: sortMergedLabels // True to sort tick labels when labels are created by merging @@ -55,16 +55,17 @@ // With sortMergedLabels set to false, tick labels will be: // > [2006, 2008, 2009, 2007] // - // Note, this property is specified on the renderOptions for the + // Note, this property is specified on the renderOptions for the // axes when creating a plot: // > axes:{xaxis:{renderer:$.jqplot.CategoryAxisRenderer, rendererOptions:{sortMergedLabels:true}}} this.sortMergedLabels = false; }; - + $.jqplot.CategoryAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer(); - $.jqplot.CategoryAxisRenderer.prototype.constructor = $.jqplot.CategoryAxisRenderer; - - $.jqplot.CategoryAxisRenderer.prototype.init = function(options){ + $.jqplot.CategoryAxisRenderer.prototype.constructor = + $.jqplot.CategoryAxisRenderer; + + $.jqplot.CategoryAxisRenderer.prototype.init = function (options) { this.groups = 1; this.groupLabels = []; this._groupLabels = []; @@ -72,48 +73,46 @@ this._barsPerGroup = null; this.reverse = false; // prop: tickRenderer - // A class of a rendering engine for creating the ticks labels displayed on the plot, + // A class of a rendering engine for creating the ticks labels displayed on the plot, // See <$.jqplot.AxisTickRenderer>. // this.tickRenderer = $.jqplot.AxisTickRenderer; // this.labelRenderer = $.jqplot.AxisLabelRenderer; - $.extend(true, this, {tickOptions:{formatString:'%d'}}, options); + $.extend(true, this, { tickOptions: { formatString: "%d" } }, options); var db = this._dataBounds; // Go through all the series attached to this axis and find // the min/max bounds for this axis. - for (var i=0; i db.max || db.max == null) { db.max = d[j][0]; } - } - else { + } else { if (d[j][1] < db.min || db.min == null) { db.min = d[j][1]; } if (d[j][1] > db.max || db.max == null) { db.max = d[j][1]; } - } + } } } - + if (this.groupLabels.length) { this.groups = this.groupLabels.length; } }; - - $.jqplot.CategoryAxisRenderer.prototype.createTicks = function() { + $.jqplot.CategoryAxisRenderer.prototype.createTicks = function () { // we're are operating on an axis here var ticks = this._ticks; var userTicks = this.ticks; @@ -130,10 +129,10 @@ // adjust with blanks if we have groups if (this.groups > 1 && !this._grouped) { var l = userTicks.length; - var skip = parseInt(l/this.groups, 10); + var skip = parseInt(l / this.groups, 10); var count = 0; - for (var i=skip; i 1 && !this._grouped) { var l = labels.length; - var skip = parseInt(l/this.groups, 10); + var skip = parseInt(l / this.groups, 10); var count = 0; - for (var i=skip; i0 && track 0 && track < skip) { t.showLabel = false; track += 1; - } - else { + } else { t.showLabel = true; track = 0; - } - t.label = t.formatter(t.formatString, labels[(i-1)/2]); + } + t.label = t.formatter(t.formatString, labels[(i - 1) / 2]); t.showMark = false; t.showGridline = false; } @@ -299,11 +303,10 @@ this._ticks.push(t); } } - }; - + // called with scope of axis - $.jqplot.CategoryAxisRenderer.prototype.draw = function(ctx, plot) { + $.jqplot.CategoryAxisRenderer.prototype.draw = function (ctx, plot) { if (this.show) { // populate the axis label and value properties. // createTicks is a method on the renderer, but @@ -312,7 +315,7 @@ // fill a div with axes labels in the right direction. // Need to pregenerate each axis to get its bounds and // position it and the labels correctly on the plot. - var dim=0; + var dim = 0; var temp; // Added for theming. if (this._elem) { @@ -321,15 +324,20 @@ this._elem.emptyForce(); } - this._elem = this._elem || $('
'); - - if (this.name == 'xaxis' || this.name == 'x2axis') { + this._elem = + this._elem || + $( + '
', + ); + + if (this.name == "xaxis" || this.name == "x2axis") { this._elem.width(this._plotDimensions.width); - } - else { + } else { this._elem.height(this._plotDimensions.height); } - + // create a _label object. this.labelOptions.axis = this.name; this._label = new this.labelRenderer(this.labelOptions); @@ -337,21 +345,27 @@ var elem = this._label.draw(ctx, plot); elem.appendTo(this._elem); } - + var t = this._ticks; - for (var i=0; i'); + for (var i = 0; i < this.groupLabels.length; i++) { + var elem = $( + '
', + ); elem.html(this.groupLabels[i]); this._groupLabels.push(elem); elem.appendTo(this._elem); @@ -359,23 +373,25 @@ } return this._elem; }; - + // called with scope of axis - $.jqplot.CategoryAxisRenderer.prototype.set = function() { + $.jqplot.CategoryAxisRenderer.prototype.set = function () { var dim = 0; var temp; var w = 0; var h = 0; - var lshow = (this._label == null) ? false : this._label.show; + var lshow = this._label == null ? false : this._label.show; if (this.show) { var t = this._ticks; - for (var i=0; i dim) { @@ -383,297 +399,368 @@ } } } - + var dim2 = 0; - for (var i=0; i dim2) { dim2 = temp; } } - + if (lshow) { w = this._label._elem.outerWidth(true); - h = this._label._elem.outerHeight(true); + h = this._label._elem.outerHeight(true); } - if (this.name == 'xaxis') { + if (this.name == "xaxis") { dim += dim2 + h; - this._elem.css({'height':dim+'px', left:'0px', bottom:'0px'}); - } - else if (this.name == 'x2axis') { + this._elem.css({ + height: dim + "px", + left: "0px", + bottom: "0px", + }); + } else if (this.name == "x2axis") { dim += dim2 + h; - this._elem.css({'height':dim+'px', left:'0px', top:'0px'}); - } - else if (this.name == 'yaxis') { + this._elem.css({ height: dim + "px", left: "0px", top: "0px" }); + } else if (this.name == "yaxis") { dim += dim2 + w; - this._elem.css({'width':dim+'px', left:'0px', top:'0px'}); - if (lshow && this._label.constructor == $.jqplot.AxisLabelRenderer) { - this._label._elem.css('width', w+'px'); + this._elem.css({ width: dim + "px", left: "0px", top: "0px" }); + if ( + lshow && + this._label.constructor == $.jqplot.AxisLabelRenderer + ) { + this._label._elem.css("width", w + "px"); } - } - else { + } else { dim += dim2 + w; - this._elem.css({'width':dim+'px', right:'0px', top:'0px'}); - if (lshow && this._label.constructor == $.jqplot.AxisLabelRenderer) { - this._label._elem.css('width', w+'px'); + this._elem.css({ width: dim + "px", right: "0px", top: "0px" }); + if ( + lshow && + this._label.constructor == $.jqplot.AxisLabelRenderer + ) { + this._label._elem.css("width", w + "px"); } } - } + } }; - + // called with scope of axis - $.jqplot.CategoryAxisRenderer.prototype.pack = function(pos, offsets) { + $.jqplot.CategoryAxisRenderer.prototype.pack = function (pos, offsets) { var ticks = this._ticks; var max = this.max; var min = this.min; var offmax = offsets.max; var offmin = offsets.min; - var lshow = (this._label == null) ? false : this._label.show; + var lshow = this._label == null ? false : this._label.show; var i; for (var p in pos) { this._elem.css(p, pos[p]); } - + this._offsets = offsets; // pixellength will be + for x axes and - for y axes becasue pixels always measured from top left. var pixellength = offmax - offmin; var unitlength = max - min; - + if (!this.reverse) { // point to unit and unit to point conversions references to Plot DOM element top left corner. - - this.u2p = function(u){ - return (u - min) * pixellength / unitlength + offmin; + + this.u2p = function (u) { + return ((u - min) * pixellength) / unitlength + offmin; }; - this.p2u = function(p){ - return (p - offmin) * unitlength / pixellength + min; + this.p2u = function (p) { + return ((p - offmin) * unitlength) / pixellength + min; }; - - if (this.name == 'xaxis' || this.name == 'x2axis'){ - this.series_u2p = function(u){ - return (u - min) * pixellength / unitlength; + + if (this.name == "xaxis" || this.name == "x2axis") { + this.series_u2p = function (u) { + return ((u - min) * pixellength) / unitlength; }; - this.series_p2u = function(p){ - return p * unitlength / pixellength + min; + this.series_p2u = function (p) { + return (p * unitlength) / pixellength + min; }; - } - - else { - this.series_u2p = function(u){ - return (u - max) * pixellength / unitlength; + } else { + this.series_u2p = function (u) { + return ((u - max) * pixellength) / unitlength; }; - this.series_p2u = function(p){ - return p * unitlength / pixellength + max; + this.series_p2u = function (p) { + return (p * unitlength) / pixellength + max; }; } - } - - else { + } else { // point to unit and unit to point conversions references to Plot DOM element top left corner. - - this.u2p = function(u){ - return offmin + (max - u) * pixellength / unitlength; + + this.u2p = function (u) { + return offmin + ((max - u) * pixellength) / unitlength; }; - this.p2u = function(p){ - return min + (p - offmin) * unitlength / pixellength; + this.p2u = function (p) { + return min + ((p - offmin) * unitlength) / pixellength; }; - - if (this.name == 'xaxis' || this.name == 'x2axis'){ - this.series_u2p = function(u){ - return (max - u) * pixellength / unitlength; + + if (this.name == "xaxis" || this.name == "x2axis") { + this.series_u2p = function (u) { + return ((max - u) * pixellength) / unitlength; }; - this.series_p2u = function(p){ - return p * unitlength / pixellength + max; + this.series_p2u = function (p) { + return (p * unitlength) / pixellength + max; }; - } - - else { - this.series_u2p = function(u){ - return (min - u) * pixellength / unitlength; + } else { + this.series_u2p = function (u) { + return ((min - u) * pixellength) / unitlength; }; - this.series_p2u = function(p){ - return p * unitlength / pixellength + min; + this.series_p2u = function (p) { + return (p * unitlength) / pixellength + min; }; } - } - - + if (this.show) { - if (this.name == 'xaxis' || this.name == 'x2axis') { - for (i=0; i= this._ticks.length-1) continue; // the last tick does not exist as there is no other group in order to have an empty one. - if (this._ticks[j]._elem && this._ticks[j].label != " ") { + for (var j = i * step; j < (i + 1) * step; j++) { + if (j >= this._ticks.length - 1) continue; // the last tick does not exist as there is no other group in order to have an empty one. + if ( + this._ticks[j]._elem && + this._ticks[j].label != " " + ) { var t = this._ticks[j]._elem; var p = t.position(); - mid += p.left + t.outerWidth(true)/2; + mid += p.left + t.outerWidth(true) / 2; count++; } } - mid = mid/count; - this._groupLabels[i].css({'left':(mid - this._groupLabels[i].outerWidth(true)/2)}); + mid = mid / count; + this._groupLabels[i].css({ + left: mid - this._groupLabels[i].outerWidth(true) / 2, + }); this._groupLabels[i].css(labeledge[0], labeledge[1]); } - } - else { - for (i=0; i 0) { - shim = -t._textRenderer.height * Math.cos(-t._textRenderer.angle) / 2; - } - else { - shim = -t.getHeight() + t._textRenderer.height * Math.cos(t._textRenderer.angle) / 2; + shim = + (-t._textRenderer.height * + Math.cos( + -t._textRenderer.angle, + )) / + 2; + } else { + shim = + -t.getHeight() + + (t._textRenderer.height * + Math.cos( + t._textRenderer.angle, + )) / + 2; } break; - case 'middle': + case "middle": // if (t.angle > 0) { // shim = -t.getHeight()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2; // } // else { // shim = -t.getHeight()/2 - t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2; // } - shim = -t.getHeight()/2; + shim = -t.getHeight() / 2; break; default: - shim = -t.getHeight()/2; + shim = -t.getHeight() / 2; break; } + } else { + shim = -t.getHeight() / 2; } - else { - shim = -t.getHeight()/2; - } - - var val = this.u2p(t.value) + shim + 'px'; - t._elem.css('top', val); + + var val = this.u2p(t.value) + shim + "px"; + t._elem.css("top", val); t.pack(); } } - - var labeledge=['left', 0]; + + var labeledge = ["left", 0]; if (lshow) { var h = this._label._elem.outerHeight(true); - this._label._elem.css('top', offmax - pixellength/2 - h/2 + 'px'); - if (this.name == 'yaxis') { - this._label._elem.css('left', '0px'); - labeledge = ['left', this._label._elem.outerWidth(true)]; + this._label._elem.css( + "top", + offmax - pixellength / 2 - h / 2 + "px", + ); + if (this.name == "yaxis") { + this._label._elem.css("left", "0px"); + labeledge = [ + "left", + this._label._elem.outerWidth(true), + ]; + } else { + this._label._elem.css("right", "0px"); + labeledge = [ + "right", + this._label._elem.outerWidth(true), + ]; } - else { - this._label._elem.css('right', '0px'); - labeledge = ['right', this._label._elem.outerWidth(true)]; - } this._label.pack(); } - + // draw the group labels, position top here, do left after label position. - var step = parseInt(this._ticks.length/this.groups, 10) + 1; // step is one more than before as we don't want to have overlaps in loops - for (i=0; i= this._ticks.length-1) continue; // the last tick does not exist as there is no other group in order to have an empty one. - if (this._ticks[j]._elem && this._ticks[j].label != " ") { + for (var j = i * step; j < (i + 1) * step; j++) { + // j must never reach (i+1)*step as we don't want to have overlap between loops + if (j >= this._ticks.length - 1) continue; // the last tick does not exist as there is no other group in order to have an empty one. + if ( + this._ticks[j]._elem && + this._ticks[j].label != " " + ) { var t = this._ticks[j]._elem; var p = t.position(); - mid += p.top + t.outerHeight()/2; + mid += p.top + t.outerHeight() / 2; count++; } } - mid = mid/count; - this._groupLabels[i].css({'top':mid - this._groupLabels[i].outerHeight()/2}); + mid = mid / count; + this._groupLabels[i].css({ + top: mid - this._groupLabels[i].outerHeight() / 2, + }); this._groupLabels[i].css(labeledge[0], labeledge[1]); - } } } - }; - - + }; })(jQuery); diff --git a/src/adminactions/static/adminactions/js/jqplot/plugins/jqplot.categoryAxisRenderer.min.js b/src/adminactions/static/adminactions/js/jqplot/plugins/jqplot.categoryAxisRenderer.min.js index 606b2846..653bd49c 100644 --- a/src/adminactions/static/adminactions/js/jqplot/plugins/jqplot.categoryAxisRenderer.min.js +++ b/src/adminactions/static/adminactions/js/jqplot/plugins/jqplot.categoryAxisRenderer.min.js @@ -1 +1,602 @@ -(function(a){a.jqplot.CategoryAxisRenderer=function(b){a.jqplot.LinearAxisRenderer.call(this);this.sortMergedLabels=false};a.jqplot.CategoryAxisRenderer.prototype=new a.jqplot.LinearAxisRenderer();a.jqplot.CategoryAxisRenderer.prototype.constructor=a.jqplot.CategoryAxisRenderer;a.jqplot.CategoryAxisRenderer.prototype.init=function(e){this.groups=1;this.groupLabels=[];this._groupLabels=[];this._grouped=false;this._barsPerGroup=null;this.reverse=false;a.extend(true,this,{tickOptions:{formatString:"%d"}},e);var b=this._dataBounds;for(var f=0;fb.max||b.max==null){b.max=h[c][0]}}else{if(h[c][1]b.max||b.max==null){b.max=h[c][1]}}}}if(this.groupLabels.length){this.groups=this.groupLabels.length}};a.jqplot.CategoryAxisRenderer.prototype.createTicks=function(){var D=this._ticks;var z=this.ticks;var F=this.name;var C=this._dataBounds;var v,A;var q,w;var d,c;var b,x;if(z.length){if(this.groups>1&&!this._grouped){var r=z.length;var p=parseInt(r/this.groups,10);var e=0;for(var x=p;x1&&!this._grouped){var r=y.length;var p=parseInt(r/this.groups,10);var e=0;for(var x=p;x0&&o');if(this.name=="xaxis"||this.name=="x2axis"){this._elem.width(this._plotDimensions.width)}else{this._elem.height(this._plotDimensions.height)}this.labelOptions.axis=this.name;this._label=new this.labelRenderer(this.labelOptions);if(this._label.show){var g=this._label.draw(b,j);g.appendTo(this._elem)}var f=this._ticks;for(var e=0;e');g.html(this.groupLabels[e]);this._groupLabels.push(g);g.appendTo(this._elem)}}return this._elem};a.jqplot.CategoryAxisRenderer.prototype.set=function(){var e=0;var m;var k=0;var f=0;var d=(this._label==null)?false:this._label.show;if(this.show){var n=this._ticks;for(var c=0;ce){e=m}}}var j=0;for(var c=0;cj){j=m}}if(d){k=this._label._elem.outerWidth(true);f=this._label._elem.outerHeight(true)}if(this.name=="xaxis"){e+=j+f;this._elem.css({height:e+"px",left:"0px",bottom:"0px"})}else{if(this.name=="x2axis"){e+=j+f;this._elem.css({height:e+"px",left:"0px",top:"0px"})}else{if(this.name=="yaxis"){e+=j+k;this._elem.css({width:e+"px",left:"0px",top:"0px"});if(d&&this._label.constructor==a.jqplot.AxisLabelRenderer){this._label._elem.css("width",k+"px")}}else{e+=j+k;this._elem.css({width:e+"px",right:"0px",top:"0px"});if(d&&this._label.constructor==a.jqplot.AxisLabelRenderer){this._label._elem.css("width",k+"px")}}}}}};a.jqplot.CategoryAxisRenderer.prototype.pack=function(e,c){var C=this._ticks;var v=this.max;var s=this.min;var n=c.max;var l=c.min;var q=(this._label==null)?false:this._label.show;var x;for(var r in e){this._elem.css(r,e[r])}this._offsets=c;var g=n-l;var k=v-s;if(!this.reverse){this.u2p=function(h){return(h-s)*g/k+l};this.p2u=function(h){return(h-l)*k/g+s};if(this.name=="xaxis"||this.name=="x2axis"){this.series_u2p=function(h){return(h-s)*g/k};this.series_p2u=function(h){return h*k/g+s}}else{this.series_u2p=function(h){return(h-v)*g/k};this.series_p2u=function(h){return h*k/g+v}}}else{this.u2p=function(h){return l+(v-h)*g/k};this.p2u=function(h){return s+(h-l)*k/g};if(this.name=="xaxis"||this.name=="x2axis"){this.series_u2p=function(h){return(v-h)*g/k};this.series_p2u=function(h){return h*k/g+v}}else{this.series_u2p=function(h){return(s-h)*g/k};this.series_p2u=function(h){return h*k/g+s}}}if(this.show){if(this.name=="xaxis"||this.name=="x2axis"){for(x=0;x=this._ticks.length-1){continue}if(this._ticks[u]._elem&&this._ticks[u].label!=" "){var o=this._ticks[u]._elem;var r=o.position();B+=r.left+o.outerWidth(true)/2;f++}}B=B/f;this._groupLabels[x].css({left:(B-this._groupLabels[x].outerWidth(true)/2)});this._groupLabels[x].css(z[0],z[1])}}else{for(x=0;x0){b=-o._textRenderer.height*Math.cos(-o._textRenderer.angle)/2}else{b=-o.getHeight()+o._textRenderer.height*Math.cos(o._textRenderer.angle)/2}break;case"middle":b=-o.getHeight()/2;break;default:b=-o.getHeight()/2;break}}else{b=-o.getHeight()/2}var D=this.u2p(o.value)+b+"px";o._elem.css("top",D);o.pack()}}var z=["left",0];if(q){var y=this._label._elem.outerHeight(true);this._label._elem.css("top",n-g/2-y/2+"px");if(this.name=="yaxis"){this._label._elem.css("left","0px");z=["left",this._label._elem.outerWidth(true)]}else{this._label._elem.css("right","0px");z=["right",this._label._elem.outerWidth(true)]}this._label.pack()}var d=parseInt(this._ticks.length/this.groups,10)+1;for(x=0;x=this._ticks.length-1){continue}if(this._ticks[u]._elem&&this._ticks[u].label!=" "){var o=this._ticks[u]._elem;var r=o.position();B+=r.top+o.outerHeight()/2;f++}}B=B/f;this._groupLabels[x].css({top:B-this._groupLabels[x].outerHeight()/2});this._groupLabels[x].css(z[0],z[1])}}}}})(jQuery); \ No newline at end of file +(function (a) { + a.jqplot.CategoryAxisRenderer = function (b) { + a.jqplot.LinearAxisRenderer.call(this); + this.sortMergedLabels = false; + }; + a.jqplot.CategoryAxisRenderer.prototype = new a.jqplot.LinearAxisRenderer(); + a.jqplot.CategoryAxisRenderer.prototype.constructor = + a.jqplot.CategoryAxisRenderer; + a.jqplot.CategoryAxisRenderer.prototype.init = function (e) { + this.groups = 1; + this.groupLabels = []; + this._groupLabels = []; + this._grouped = false; + this._barsPerGroup = null; + this.reverse = false; + a.extend(true, this, { tickOptions: { formatString: "%d" } }, e); + var b = this._dataBounds; + for (var f = 0; f < this._series.length; f++) { + var g = this._series[f]; + if (g.groups) { + this.groups = g.groups; + } + var h = g.data; + for (var c = 0; c < h.length; c++) { + if (this.name == "xaxis" || this.name == "x2axis") { + if (h[c][0] < b.min || b.min == null) { + b.min = h[c][0]; + } + if (h[c][0] > b.max || b.max == null) { + b.max = h[c][0]; + } + } else { + if (h[c][1] < b.min || b.min == null) { + b.min = h[c][1]; + } + if (h[c][1] > b.max || b.max == null) { + b.max = h[c][1]; + } + } + } + } + if (this.groupLabels.length) { + this.groups = this.groupLabels.length; + } + }; + a.jqplot.CategoryAxisRenderer.prototype.createTicks = function () { + var D = this._ticks; + var z = this.ticks; + var F = this.name; + var C = this._dataBounds; + var v, A; + var q, w; + var d, c; + var b, x; + if (z.length) { + if (this.groups > 1 && !this._grouped) { + var r = z.length; + var p = parseInt(r / this.groups, 10); + var e = 0; + for (var x = p; x < r; x += p) { + z.splice(x + e, 0, " "); + e++; + } + this._grouped = true; + } + this.min = 0.5; + this.max = z.length + 0.5; + var m = this.max - this.min; + this.numberTicks = 2 * z.length + 1; + for (x = 0; x < z.length; x++) { + b = this.min + (2 * x * m) / (this.numberTicks - 1); + var h = new this.tickRenderer(this.tickOptions); + h.showLabel = false; + h.setTick(b, this.name); + this._ticks.push(h); + var h = new this.tickRenderer(this.tickOptions); + h.label = z[x]; + h.showMark = false; + h.showGridline = false; + h.setTick(b + 0.5, this.name); + this._ticks.push(h); + } + var h = new this.tickRenderer(this.tickOptions); + h.showLabel = false; + h.setTick(b + 1, this.name); + this._ticks.push(h); + } else { + if (F == "xaxis" || F == "x2axis") { + v = this._plotDimensions.width; + } else { + v = this._plotDimensions.height; + } + if ( + this.min != null && + this.max != null && + this.numberTicks != null + ) { + this.tickInterval = null; + } + if ( + this.min != null && + this.max != null && + this.tickInterval != null + ) { + if ( + parseInt((this.max - this.min) / this.tickInterval, 10) != + (this.max - this.min) / this.tickInterval + ) { + this.tickInterval = null; + } + } + var y = []; + var B = 0; + var q = 0.5; + var w, E; + var f = false; + for (var x = 0; x < this._series.length; x++) { + var k = this._series[x]; + for (var u = 0; u < k.data.length; u++) { + if (this.name == "xaxis" || this.name == "x2axis") { + E = k.data[u][0]; + } else { + E = k.data[u][1]; + } + if (a.inArray(E, y) == -1) { + f = true; + B += 1; + y.push(E); + } + } + } + if (f && this.sortMergedLabels) { + if (typeof y[0] == "string") { + y.sort(); + } else { + y.sort(function (j, i) { + return j - i; + }); + } + } + this.ticks = y; + for (var x = 0; x < this._series.length; x++) { + var k = this._series[x]; + for (var u = 0; u < k.data.length; u++) { + if (this.name == "xaxis" || this.name == "x2axis") { + E = k.data[u][0]; + } else { + E = k.data[u][1]; + } + var n = a.inArray(E, y) + 1; + if (this.name == "xaxis" || this.name == "x2axis") { + k.data[u][0] = n; + } else { + k.data[u][1] = n; + } + } + } + if (this.groups > 1 && !this._grouped) { + var r = y.length; + var p = parseInt(r / this.groups, 10); + var e = 0; + for (var x = p; x < r; x += p + 1) { + y[x] = " "; + } + this._grouped = true; + } + w = B + 0.5; + if (this.numberTicks == null) { + this.numberTicks = 2 * B + 1; + } + var m = w - q; + this.min = q; + this.max = w; + var o = 0; + var g = parseInt(3 + v / 10, 10); + var p = parseInt(B / g, 10); + if (this.tickInterval == null) { + this.tickInterval = m / (this.numberTicks - 1); + } + for (var x = 0; x < this.numberTicks; x++) { + b = this.min + x * this.tickInterval; + var h = new this.tickRenderer(this.tickOptions); + if (x / 2 == parseInt(x / 2, 10)) { + h.showLabel = false; + h.showMark = true; + } else { + if (p > 0 && o < p) { + h.showLabel = false; + o += 1; + } else { + h.showLabel = true; + o = 0; + } + h.label = h.formatter(h.formatString, y[(x - 1) / 2]); + h.showMark = false; + h.showGridline = false; + } + h.setTick(b, this.name); + this._ticks.push(h); + } + } + }; + a.jqplot.CategoryAxisRenderer.prototype.draw = function (b, j) { + if (this.show) { + this.renderer.createTicks.call(this); + var h = 0; + var c; + if (this._elem) { + this._elem.emptyForce(); + } + this._elem = + this._elem || + a( + '
', + ); + if (this.name == "xaxis" || this.name == "x2axis") { + this._elem.width(this._plotDimensions.width); + } else { + this._elem.height(this._plotDimensions.height); + } + this.labelOptions.axis = this.name; + this._label = new this.labelRenderer(this.labelOptions); + if (this._label.show) { + var g = this._label.draw(b, j); + g.appendTo(this._elem); + } + var f = this._ticks; + for (var e = 0; e < f.length; e++) { + var d = f[e]; + if (d.showLabel && (!d.isMinorTick || this.showMinorTicks)) { + var g = d.draw(b, j); + g.appendTo(this._elem); + } + } + this._groupLabels = []; + for (var e = 0; e < this.groupLabels.length; e++) { + var g = a( + '
', + ); + g.html(this.groupLabels[e]); + this._groupLabels.push(g); + g.appendTo(this._elem); + } + } + return this._elem; + }; + a.jqplot.CategoryAxisRenderer.prototype.set = function () { + var e = 0; + var m; + var k = 0; + var f = 0; + var d = this._label == null ? false : this._label.show; + if (this.show) { + var n = this._ticks; + for (var c = 0; c < n.length; c++) { + var g = n[c]; + if (g.showLabel && (!g.isMinorTick || this.showMinorTicks)) { + if (this.name == "xaxis" || this.name == "x2axis") { + m = g._elem.outerHeight(true); + } else { + m = g._elem.outerWidth(true); + } + if (m > e) { + e = m; + } + } + } + var j = 0; + for (var c = 0; c < this._groupLabels.length; c++) { + var b = this._groupLabels[c]; + if (this.name == "xaxis" || this.name == "x2axis") { + m = b.outerHeight(true); + } else { + m = b.outerWidth(true); + } + if (m > j) { + j = m; + } + } + if (d) { + k = this._label._elem.outerWidth(true); + f = this._label._elem.outerHeight(true); + } + if (this.name == "xaxis") { + e += j + f; + this._elem.css({ + height: e + "px", + left: "0px", + bottom: "0px", + }); + } else { + if (this.name == "x2axis") { + e += j + f; + this._elem.css({ + height: e + "px", + left: "0px", + top: "0px", + }); + } else { + if (this.name == "yaxis") { + e += j + k; + this._elem.css({ + width: e + "px", + left: "0px", + top: "0px", + }); + if ( + d && + this._label.constructor == + a.jqplot.AxisLabelRenderer + ) { + this._label._elem.css("width", k + "px"); + } + } else { + e += j + k; + this._elem.css({ + width: e + "px", + right: "0px", + top: "0px", + }); + if ( + d && + this._label.constructor == + a.jqplot.AxisLabelRenderer + ) { + this._label._elem.css("width", k + "px"); + } + } + } + } + } + }; + a.jqplot.CategoryAxisRenderer.prototype.pack = function (e, c) { + var C = this._ticks; + var v = this.max; + var s = this.min; + var n = c.max; + var l = c.min; + var q = this._label == null ? false : this._label.show; + var x; + for (var r in e) { + this._elem.css(r, e[r]); + } + this._offsets = c; + var g = n - l; + var k = v - s; + if (!this.reverse) { + this.u2p = function (h) { + return ((h - s) * g) / k + l; + }; + this.p2u = function (h) { + return ((h - l) * k) / g + s; + }; + if (this.name == "xaxis" || this.name == "x2axis") { + this.series_u2p = function (h) { + return ((h - s) * g) / k; + }; + this.series_p2u = function (h) { + return (h * k) / g + s; + }; + } else { + this.series_u2p = function (h) { + return ((h - v) * g) / k; + }; + this.series_p2u = function (h) { + return (h * k) / g + v; + }; + } + } else { + this.u2p = function (h) { + return l + ((v - h) * g) / k; + }; + this.p2u = function (h) { + return s + ((h - l) * k) / g; + }; + if (this.name == "xaxis" || this.name == "x2axis") { + this.series_u2p = function (h) { + return ((v - h) * g) / k; + }; + this.series_p2u = function (h) { + return (h * k) / g + v; + }; + } else { + this.series_u2p = function (h) { + return ((s - h) * g) / k; + }; + this.series_p2u = function (h) { + return (h * k) / g + s; + }; + } + } + if (this.show) { + if (this.name == "xaxis" || this.name == "x2axis") { + for (x = 0; x < C.length; x++) { + var o = C[x]; + if (o.show && o.showLabel) { + var b; + if ( + o.constructor == a.jqplot.CanvasAxisTickRenderer && + o.angle + ) { + var A = this.name == "xaxis" ? 1 : -1; + switch (o.labelPosition) { + case "auto": + if (A * o.angle < 0) { + b = + -o.getWidth() + + (o._textRenderer.height * + Math.sin( + -o._textRenderer.angle, + )) / + 2; + } else { + b = + (-o._textRenderer.height * + Math.sin( + o._textRenderer.angle, + )) / + 2; + } + break; + case "end": + b = + -o.getWidth() + + (o._textRenderer.height * + Math.sin(-o._textRenderer.angle)) / + 2; + break; + case "start": + b = + (-o._textRenderer.height * + Math.sin(o._textRenderer.angle)) / + 2; + break; + case "middle": + b = + -o.getWidth() / 2 + + (o._textRenderer.height * + Math.sin(-o._textRenderer.angle)) / + 2; + break; + default: + b = + -o.getWidth() / 2 + + (o._textRenderer.height * + Math.sin(-o._textRenderer.angle)) / + 2; + break; + } + } else { + b = -o.getWidth() / 2; + } + var D = this.u2p(o.value) + b + "px"; + o._elem.css("left", D); + o.pack(); + } + } + var z = ["bottom", 0]; + if (q) { + var m = this._label._elem.outerWidth(true); + this._label._elem.css("left", l + g / 2 - m / 2 + "px"); + if (this.name == "xaxis") { + this._label._elem.css("bottom", "0px"); + z = ["bottom", this._label._elem.outerHeight(true)]; + } else { + this._label._elem.css("top", "0px"); + z = ["top", this._label._elem.outerHeight(true)]; + } + this._label.pack(); + } + var d = parseInt(this._ticks.length / this.groups, 10) + 1; + for (x = 0; x < this._groupLabels.length; x++) { + var B = 0; + var f = 0; + for (var u = x * d; u < (x + 1) * d; u++) { + if (u >= this._ticks.length - 1) { + continue; + } + if ( + this._ticks[u]._elem && + this._ticks[u].label != " " + ) { + var o = this._ticks[u]._elem; + var r = o.position(); + B += r.left + o.outerWidth(true) / 2; + f++; + } + } + B = B / f; + this._groupLabels[x].css({ + left: B - this._groupLabels[x].outerWidth(true) / 2, + }); + this._groupLabels[x].css(z[0], z[1]); + } + } else { + for (x = 0; x < C.length; x++) { + var o = C[x]; + if (o.show && o.showLabel) { + var b; + if ( + o.constructor == a.jqplot.CanvasAxisTickRenderer && + o.angle + ) { + var A = this.name == "yaxis" ? 1 : -1; + switch (o.labelPosition) { + case "auto": + case "end": + if (A * o.angle < 0) { + b = + (-o._textRenderer.height * + Math.cos( + -o._textRenderer.angle, + )) / + 2; + } else { + b = + -o.getHeight() + + (o._textRenderer.height * + Math.cos( + o._textRenderer.angle, + )) / + 2; + } + break; + case "start": + if (o.angle > 0) { + b = + (-o._textRenderer.height * + Math.cos( + -o._textRenderer.angle, + )) / + 2; + } else { + b = + -o.getHeight() + + (o._textRenderer.height * + Math.cos( + o._textRenderer.angle, + )) / + 2; + } + break; + case "middle": + b = -o.getHeight() / 2; + break; + default: + b = -o.getHeight() / 2; + break; + } + } else { + b = -o.getHeight() / 2; + } + var D = this.u2p(o.value) + b + "px"; + o._elem.css("top", D); + o.pack(); + } + } + var z = ["left", 0]; + if (q) { + var y = this._label._elem.outerHeight(true); + this._label._elem.css("top", n - g / 2 - y / 2 + "px"); + if (this.name == "yaxis") { + this._label._elem.css("left", "0px"); + z = ["left", this._label._elem.outerWidth(true)]; + } else { + this._label._elem.css("right", "0px"); + z = ["right", this._label._elem.outerWidth(true)]; + } + this._label.pack(); + } + var d = parseInt(this._ticks.length / this.groups, 10) + 1; + for (x = 0; x < this._groupLabels.length; x++) { + var B = 0; + var f = 0; + for (var u = x * d; u < (x + 1) * d; u++) { + if (u >= this._ticks.length - 1) { + continue; + } + if ( + this._ticks[u]._elem && + this._ticks[u].label != " " + ) { + var o = this._ticks[u]._elem; + var r = o.position(); + B += r.top + o.outerHeight() / 2; + f++; + } + } + B = B / f; + this._groupLabels[x].css({ + top: B - this._groupLabels[x].outerHeight() / 2, + }); + this._groupLabels[x].css(z[0], z[1]); + } + } + } + }; +})(jQuery); diff --git a/src/adminactions/static/adminactions/js/jqplot/plugins/jqplot.pieRenderer.js b/src/adminactions/static/adminactions/js/jqplot/plugins/jqplot.pieRenderer.js index 20eb797f..3171833c 100644 --- a/src/adminactions/static/adminactions/js/jqplot/plugins/jqplot.pieRenderer.js +++ b/src/adminactions/static/adminactions/js/jqplot/plugins/jqplot.pieRenderer.js @@ -6,13 +6,13 @@ * Revision: 1250 * * Copyright (c) 2009-2013 Chris Leonello - * jqPlot is currently available for use in all personal or commercial projects - * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL - * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can - * choose the license that best suits your project and use it accordingly. + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. * - * Although not required, the author would appreciate an email letting him - * know of any substantial use of jqPlot. You can reach the author at: + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: * chris at jqplot dot com or see http://www.jqplot.com/info.php . * * If you are feeling kind and generous, consider supporting the project by @@ -26,23 +26,23 @@ * http://hexmen.com/js/sprintf.js * The author (Ash Searle) has placed this code in the public domain: * "This code is unrestricted: you are free to use it however you like." - * + * */ -(function($) { +(function ($) { /** * Class: $.jqplot.PieRenderer * Plugin renderer to draw a pie chart. * x values, if present, will be used as slice labels. * y values give slice size. - * - * To use this renderer, you need to include the + * + * To use this renderer, you need to include the * pie renderer plugin, for example: - * + * * > - * + * * Properties described here are passed into the $.jqplot function * as options on the series renderer. For example: - * + * * > plot2 = $.jqplot('chart2', [s1, s2], { * > seriesDefaults: { * > renderer:$.jqplot.PieRenderer, @@ -52,12 +52,12 @@ * > } * > } * > }); - * + * * A pie plot will trigger events on the plot target * according to user interaction. All events return the event object, - * the series index, the point (slice) index, and the point data for + * the series index, the point (slice) index, and the point data for * the appropriate slice. - * + * * 'jqplotDataMouseOver' - triggered when user mouseing over a slice. * 'jqplotDataHighlight' - triggered the first time user mouses over a slice, * if highlighting is enabled. @@ -67,15 +67,15 @@ * 'jqplotDataRightClick' - tiggered when the user right clicks on a slice if * the "captureRightClick" option is set to true on the plot. */ - $.jqplot.PieRenderer = function(){ + $.jqplot.PieRenderer = function () { $.jqplot.LineRenderer.call(this); }; - + $.jqplot.PieRenderer.prototype = new $.jqplot.LineRenderer(); $.jqplot.PieRenderer.prototype.constructor = $.jqplot.PieRenderer; - + // called with scope of a series - $.jqplot.PieRenderer.prototype.init = function(options, plot) { + $.jqplot.PieRenderer.prototype.init = function (options, plot) { // Group: Properties // // prop: diameter @@ -91,14 +91,14 @@ // true or false, whether to fil the slices. this.fill = true; // prop: shadowOffset - // offset of the shadow from the slice and offset of + // offset of the shadow from the slice and offset of // each successive stroke of the shadow from the last. this.shadowOffset = 2; // prop: shadowAlpha // transparency of the shadow (0 = transparent, 1 = opaque) this.shadowAlpha = 0.07; // prop: shadowDepth - // number of strokes to apply to the shadow, + // number of strokes to apply to the shadow, // each stroke offset shadowOffset from the last. this.shadowDepth = 5; // prop: highlightMouseOver @@ -115,7 +115,7 @@ // prop: dataLabels // Either 'label', 'value', 'percent' or an array of labels to place on the pie slices. // Defaults to percentage of each pie slice. - this.dataLabels = 'percent'; + this.dataLabels = "percent"; // prop: showDataLabels // true to show data labels on slices. this.showDataLabels = false; @@ -138,7 +138,7 @@ // False to set the inside facing edge of the label at its position. this.dataLabelCenterOn = true; // prop: startAngle - // Angle to start drawing pie in degrees. + // Angle to start drawing pie in degrees. // According to orientation of canvas coordinate system: // 0 = on the positive x axis // -90 = on the positive y axis. @@ -148,13 +148,13 @@ this.tickRenderer = $.jqplot.PieTickRenderer; // Used as check for conditions where pie shouldn't be drawn. this._drawData = true; - this._type = 'pie'; - + this._type = "pie"; + // if user has passed in highlightMouseDown option and not set highlightMouseOver, disable highlightMouseOver if (options.highlightMouseDown && options.highlightMouseOver == null) { options.highlightMouseOver = false; } - + $.extend(true, this, options); if (this.sliceMargin < 0) { @@ -167,93 +167,106 @@ this._sliceAngles = []; // index of the currently highlighted point, if any this._highlightedPoint = null; - + // set highlight colors if none provided if (this.highlightColors.length == 0) { - for (var i=0; i 570) ? newrgb[j] * 0.8 : newrgb[j] + 0.3 * (255 - newrgb[j]); + newrgb[j] = + sum > 570 + ? newrgb[j] * 0.8 + : newrgb[j] + 0.3 * (255 - newrgb[j]); newrgb[j] = parseInt(newrgb[j], 10); } - this.highlightColors.push('rgb('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+')'); + this.highlightColors.push( + "rgb(" + + newrgb[0] + + "," + + newrgb[1] + + "," + + newrgb[2] + + ")", + ); } } - - this.highlightColorGenerator = new $.jqplot.ColorGenerator(this.highlightColors); - + + this.highlightColorGenerator = new $.jqplot.ColorGenerator( + this.highlightColors, + ); + plot.postParseOptionsHooks.addOnce(postParseOptions); plot.postInitHooks.addOnce(postInit); - plot.eventListenerHooks.addOnce('jqplotMouseMove', handleMove); - plot.eventListenerHooks.addOnce('jqplotMouseDown', handleMouseDown); - plot.eventListenerHooks.addOnce('jqplotMouseUp', handleMouseUp); - plot.eventListenerHooks.addOnce('jqplotClick', handleClick); - plot.eventListenerHooks.addOnce('jqplotRightClick', handleRightClick); + plot.eventListenerHooks.addOnce("jqplotMouseMove", handleMove); + plot.eventListenerHooks.addOnce("jqplotMouseDown", handleMouseDown); + plot.eventListenerHooks.addOnce("jqplotMouseUp", handleMouseUp); + plot.eventListenerHooks.addOnce("jqplotClick", handleClick); + plot.eventListenerHooks.addOnce("jqplotRightClick", handleRightClick); plot.postDrawHooks.addOnce(postPlotDraw); }; - - $.jqplot.PieRenderer.prototype.setGridData = function(plot) { + + $.jqplot.PieRenderer.prototype.setGridData = function (plot) { // set gridData property. This will hold angle in radians of each data point. var stack = []; var td = []; - var sa = this.startAngle/180*Math.PI; + var sa = (this.startAngle / 180) * Math.PI; var tot = 0; // don't know if we have any valid data yet, so set plot to not draw. this._drawData = false; - for (var i=0; i0) { - stack[i] += stack[i-1]; + if (i > 0) { + stack[i] += stack[i - 1]; } tot += this.data[i][1]; } - var fact = Math.PI*2/stack[stack.length - 1]; - - for (var i=0; i0) { - stack[i] += stack[i-1]; + if (i > 0) { + stack[i] += stack[i - 1]; } tot += data[i][1]; } - var fact = Math.PI*2/stack[stack.length - 1]; - - for (var i=0; i 6.282 + this.startAngle) { + if (ang2 > 6.282 + this.startAngle) { ang2 = 6.282 + this.startAngle; if (ang1 > ang2) { ang1 = 6.281 + this.startAngle; @@ -329,62 +356,64 @@ // ugly line on unfilled pies. if (ang1 >= ang2) { return; - } - - ctx.beginPath(); + } + + ctx.beginPath(); ctx.fillStyle = color; ctx.strokeStyle = color; ctx.lineWidth = lineWidth; ctx.arc(0, 0, rad, ang1, ang2, false); - ctx.lineTo(0,0); + ctx.lineTo(0, 0); ctx.closePath(); - + if (fill) { ctx.fill(); - } - else { + } else { ctx.stroke(); } } }; - + // called with scope of series $.jqplot.PieRenderer.prototype.draw = function (ctx, gd, options, plot) { var i; - var opts = (options != undefined) ? options : {}; + var opts = options != undefined ? options : {}; // offset and direction of offset due to legend placement var offx = 0; var offy = 0; var trans = 1; var colorGenerator = new $.jqplot.ColorGenerator(this.seriesColors); - if (options.legendInfo && options.legendInfo.placement == 'insideGrid') { + if ( + options.legendInfo && + options.legendInfo.placement == "insideGrid" + ) { var li = options.legendInfo; switch (li.location) { - case 'nw': + case "nw": offx = li.width + li.xoffset; break; - case 'w': + case "w": offx = li.width + li.xoffset; break; - case 'sw': + case "sw": offx = li.width + li.xoffset; break; - case 'ne': + case "ne": offx = li.width + li.xoffset; trans = -1; break; - case 'e': + case "e": offx = li.width + li.xoffset; trans = -1; break; - case 'se': + case "se": offx = li.width + li.xoffset; trans = -1; break; - case 'n': + case "n": offy = li.height + li.yoffset; break; - case 's': + case "s": offy = li.height + li.yoffset; trans = -1; break; @@ -392,16 +421,16 @@ break; } } - - var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow; - var fill = (opts.fill != undefined) ? opts.fill : this.fill; + + var shadow = opts.shadow != undefined ? opts.shadow : this.shadow; + var fill = opts.fill != undefined ? opts.fill : this.fill; var cw = ctx.canvas.width; var ch = ctx.canvas.height; var w = cw - offx - 2 * this.padding; var h = ch - offy - 2 * this.padding; - var mindim = Math.min(w,h); + var mindim = Math.min(w, h); var d = mindim; - + // Fixes issue #272. Thanks hugwijst! // reset slice angles array. this._sliceAngles = []; @@ -410,109 +439,144 @@ if (this.fill == false) { sm += this.lineWidth; } - + var rprime; var maxrprime = 0; var ang, ang1, ang2, shadowColor; - var sa = this.startAngle / 180 * Math.PI; + var sa = (this.startAngle / 180) * Math.PI; // have to pre-draw shadows, so loop throgh here and calculate some values also. - for (var i=0, l=gd.length; i Math.PI) { - maxrprime = Math.max(rprime, maxrprime); + if (Math.abs(ang2 - ang1) > Math.PI) { + maxrprime = Math.max(rprime, maxrprime); } } if (this.diameter != null && this.diameter > 0) { - this._diameter = this.diameter - 2*maxrprime; - } - else { - this._diameter = d - 2*maxrprime; + this._diameter = this.diameter - 2 * maxrprime; + } else { + this._diameter = d - 2 * maxrprime; } // Need to check for undersized pie. This can happen if // plot area too small and legend is too big. if (this._diameter < 6) { - $.jqplot.log('Diameter of pie too small, not rendering.'); + $.jqplot.log("Diameter of pie too small, not rendering."); return; } - var r = this._radius = this._diameter/2; + var r = (this._radius = this._diameter / 2); - this._center = [(cw - trans * offx)/2 + trans * offx + maxrprime * Math.cos(sa), (ch - trans*offy)/2 + trans * offy + maxrprime * Math.sin(sa)]; + this._center = [ + (cw - trans * offx) / 2 + trans * offx + maxrprime * Math.cos(sa), + (ch - trans * offy) / 2 + trans * offy + maxrprime * Math.sin(sa), + ]; if (this.shadow) { - for (var i=0, l=gd.length; i= this.dataLabelThreshold) { - var fstr, avgang = (this._sliceAngles[i][0] + this._sliceAngles[i][1])/2, label; - - if (this.dataLabels == 'label') { - fstr = this.dataLabelFormatString || '%s'; + + for (var i = 0; i < gd.length; i++) { + this.renderer.drawSlice.call( + this, + ctx, + this._sliceAngles[i][0], + this._sliceAngles[i][1], + colorGenerator.next(), + false, + ); + + if ( + this.showDataLabels && + gd[i][2] * 100 >= this.dataLabelThreshold + ) { + var fstr, + avgang = + (this._sliceAngles[i][0] + this._sliceAngles[i][1]) / 2, + label; + + if (this.dataLabels == "label") { + fstr = this.dataLabelFormatString || "%s"; label = $.jqplot.sprintf(fstr, gd[i][0]); - } - else if (this.dataLabels == 'value') { - fstr = this.dataLabelFormatString || '%d'; + } else if (this.dataLabels == "value") { + fstr = this.dataLabelFormatString || "%d"; label = $.jqplot.sprintf(fstr, this.data[i][1]); - } - else if (this.dataLabels == 'percent') { - fstr = this.dataLabelFormatString || '%d%%'; - label = $.jqplot.sprintf(fstr, gd[i][2]*100); - } - else if (this.dataLabels.constructor == Array) { - fstr = this.dataLabelFormatString || '%s'; + } else if (this.dataLabels == "percent") { + fstr = this.dataLabelFormatString || "%d%%"; + label = $.jqplot.sprintf(fstr, gd[i][2] * 100); + } else if (this.dataLabels.constructor == Array) { + fstr = this.dataLabelFormatString || "%s"; label = $.jqplot.sprintf(fstr, this.dataLabels[i]); } - - var fact = (this._radius ) * this.dataLabelPositionFactor + this.sliceMargin + this.dataLabelNudge; - - var x = this._center[0] + Math.cos(avgang) * fact + this.canvas._offsets.left; - var y = this._center[1] + Math.sin(avgang) * fact + this.canvas._offsets.top; - - var labelelem = $('
' + label + '
').insertBefore(plot.eventCanvas._elem); + + var fact = + this._radius * this.dataLabelPositionFactor + + this.sliceMargin + + this.dataLabelNudge; + + var x = + this._center[0] + + Math.cos(avgang) * fact + + this.canvas._offsets.left; + var y = + this._center[1] + + Math.sin(avgang) * fact + + this.canvas._offsets.top; + + var labelelem = $( + '
' + + label + + "
", + ).insertBefore(plot.eventCanvas._elem); if (this.dataLabelCenterOn) { - x -= labelelem.width()/2; - y -= labelelem.height()/2; - } - else { - x -= labelelem.width() * Math.sin(avgang/2); - y -= labelelem.height()/2; + x -= labelelem.width() / 2; + y -= labelelem.height() / 2; + } else { + x -= labelelem.width() * Math.sin(avgang / 2); + y -= labelelem.height() / 2; } x = Math.round(x); y = Math.round(y); - labelelem.css({left: x, top: y}); + labelelem.css({ left: x, top: y }); } - } + } }; - - $.jqplot.PieAxisRenderer = function() { + + $.jqplot.PieAxisRenderer = function () { $.jqplot.LinearAxisRenderer.call(this); }; - + $.jqplot.PieAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer(); $.jqplot.PieAxisRenderer.prototype.constructor = $.jqplot.PieAxisRenderer; - - + // There are no traditional axes on a pie chart. We just need to provide // dummy objects with properties so the plot will render. // called with scope of axis object. - $.jqplot.PieAxisRenderer.prototype.init = function(options){ + $.jqplot.PieAxisRenderer.prototype.init = function (options) { // this.tickRenderer = $.jqplot.PieTickRenderer; $.extend(true, this, options); @@ -521,31 +585,29 @@ // and provide u2p and p2u functionality for mouse cursor, etc. // for convenience set _dataBounds to 0 and 100 and // set min/max to 0 and 100. - this._dataBounds = {min:0, max:100}; + this._dataBounds = { min: 0, max: 100 }; this.min = 0; this.max = 100; this.showTicks = false; this.ticks = []; this.showMark = false; - this.show = false; + this.show = false; }; - - - - - $.jqplot.PieLegendRenderer = function(){ + + $.jqplot.PieLegendRenderer = function () { $.jqplot.TableLegendRenderer.call(this); }; - + $.jqplot.PieLegendRenderer.prototype = new $.jqplot.TableLegendRenderer(); - $.jqplot.PieLegendRenderer.prototype.constructor = $.jqplot.PieLegendRenderer; - + $.jqplot.PieLegendRenderer.prototype.constructor = + $.jqplot.PieLegendRenderer; + /** * Class: $.jqplot.PieLegendRenderer * Legend Renderer specific to pie plots. Set by default * when user creates a pie plot. */ - $.jqplot.PieLegendRenderer.prototype.init = function(options) { + $.jqplot.PieLegendRenderer.prototype.init = function (options) { // Group: Properties // // prop: numberRows @@ -556,176 +618,184 @@ this.numberColumns = null; $.extend(true, this, options); }; - + // called with context of legend - $.jqplot.PieLegendRenderer.prototype.draw = function() { + $.jqplot.PieLegendRenderer.prototype.draw = function () { var legend = this; if (this.show) { var series = this._series; + this._elem = $(document.createElement("table")); + this._elem.addClass("jqplot-table-legend"); - this._elem = $(document.createElement('table')); - this._elem.addClass('jqplot-table-legend'); - - var ss = {position:'absolute'}; + var ss = { position: "absolute" }; if (this.background) { - ss['background'] = this.background; + ss["background"] = this.background; } if (this.border) { - ss['border'] = this.border; + ss["border"] = this.border; } if (this.fontSize) { - ss['fontSize'] = this.fontSize; + ss["fontSize"] = this.fontSize; } if (this.fontFamily) { - ss['fontFamily'] = this.fontFamily; + ss["fontFamily"] = this.fontFamily; } if (this.textColor) { - ss['textColor'] = this.textColor; + ss["textColor"] = this.textColor; } if (this.marginTop != null) { - ss['marginTop'] = this.marginTop; + ss["marginTop"] = this.marginTop; } if (this.marginBottom != null) { - ss['marginBottom'] = this.marginBottom; + ss["marginBottom"] = this.marginBottom; } if (this.marginLeft != null) { - ss['marginLeft'] = this.marginLeft; + ss["marginLeft"] = this.marginLeft; } if (this.marginRight != null) { - ss['marginRight'] = this.marginRight; + ss["marginRight"] = this.marginRight; } this._elem.css(ss); // Pie charts legends don't go by number of series, but by number of data points // in the series. Refactor things here for that. - - var pad = false, + + var pad = false, reverse = false, - nr, + nr, nc; var s = series[0]; var colorGenerator = new $.jqplot.ColorGenerator(s.seriesColors); - + if (s.show) { var pd = s.data; if (this.numberRows) { nr = this.numberRows; - if (!this.numberColumns){ - nc = Math.ceil(pd.length/nr); - } - else{ + if (!this.numberColumns) { + nc = Math.ceil(pd.length / nr); + } else { nc = this.numberColumns; } - } - else if (this.numberColumns) { + } else if (this.numberColumns) { nc = this.numberColumns; - nr = Math.ceil(pd.length/this.numberColumns); - } - else { + nr = Math.ceil(pd.length / this.numberColumns); + } else { nr = pd.length; nc = 1; } - + var i, j; - var tr, td1, td2; + var tr, td1, td2; var lt, rs, color; - var idx = 0; - var div0, div1; - - for (i=0; i0){ + if (!reverse) { + if (i > 0) { pad = true; - } - else{ + } else { pad = false; } - } - else{ - if (i == nr -1){ + } else { + if (i == nr - 1) { pad = false; - } - else{ + } else { pad = true; } } - rs = (pad) ? this.rowSpacing : '0'; - - + rs = pad ? this.rowSpacing : "0"; - td1 = $(document.createElement('td')); - td1.addClass('jqplot-table-legend jqplot-table-legend-swatch'); - td1.css({textAlign: 'center', paddingTop: rs}); + td1 = $(document.createElement("td")); + td1.addClass( + "jqplot-table-legend jqplot-table-legend-swatch", + ); + td1.css({ textAlign: "center", paddingTop: rs }); - div0 = $(document.createElement('div')); - div0.addClass('jqplot-table-legend-swatch-outline'); - div1 = $(document.createElement('div')); - div1.addClass('jqplot-table-legend-swatch'); - div1.css({backgroundColor: color, borderColor: color}); + div0 = $(document.createElement("div")); + div0.addClass("jqplot-table-legend-swatch-outline"); + div1 = $(document.createElement("div")); + div1.addClass("jqplot-table-legend-swatch"); + div1.css({ + backgroundColor: color, + borderColor: color, + }); td1.append(div0.append(div1)); - td2 = $(document.createElement('td')); - td2.addClass('jqplot-table-legend jqplot-table-legend-label'); - td2.css('paddingTop', rs); + td2 = $(document.createElement("td")); + td2.addClass( + "jqplot-table-legend jqplot-table-legend-label", + ); + td2.css("paddingTop", rs); - if (this.escapeHtml){ + if (this.escapeHtml) { td2.text(lt); - } - else { + } else { td2.html(lt); } if (reverse) { td2.prependTo(tr); td1.prependTo(tr); - } - else { + } else { td1.appendTo(tr); td2.appendTo(tr); } pad = true; } idx++; - } + } } } } - return this._elem; + return this._elem; }; - - $.jqplot.PieRenderer.prototype.handleMove = function(ev, gridpos, datapos, neighbor, plot) { + + $.jqplot.PieRenderer.prototype.handleMove = function ( + ev, + gridpos, + datapos, + neighbor, + plot, + ) { if (neighbor) { - var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; - plot.target.trigger('jqplotDataMouseOver', ins); - if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.pieRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) { - plot.target.trigger('jqplotDataHighlight', ins); - highlight (plot, ins[0], ins[1]); + var ins = [ + neighbor.seriesIndex, + neighbor.pointIndex, + neighbor.data, + ]; + plot.target.trigger("jqplotDataMouseOver", ins); + if ( + plot.series[ins[0]].highlightMouseOver && + !( + ins[0] == plot.plugins.pieRenderer.highlightedSeriesIndex && + ins[1] == plot.series[ins[0]]._highlightedPoint + ) + ) { + plot.target.trigger("jqplotDataHighlight", ins); + highlight(plot, ins[0], ins[1]); } - } - else if (neighbor == null) { - unhighlight (plot); + } else if (neighbor == null) { + unhighlight(plot); } }; - - + // this.eventCanvas._elem.bind($.jqplot.eventListenerHooks[i][0], {plot:this}, $.jqplot.eventListenerHooks[i][1]); - + // setup default renderers for axes and legend so user doesn't have to // called with scope of plot function preInit(target, data, options) { @@ -737,25 +807,24 @@ var setopts = false; if (options.seriesDefaults.renderer == $.jqplot.PieRenderer) { setopts = true; - } - else if (options.series) { - for (var i=0; i < options.series.length; i++) { + } else if (options.series) { + for (var i = 0; i < options.series.length; i++) { if (options.series[i].renderer == $.jqplot.PieRenderer) { setopts = true; } } } - + if (setopts) { options.axesDefaults.renderer = $.jqplot.PieAxisRenderer; options.legend.renderer = $.jqplot.PieLegendRenderer; options.legend.preDraw = true; - options.seriesDefaults.pointLabels = {show: false}; + options.seriesDefaults.pointLabels = { show: false }; } } - + function postInit(target, data, options) { - for (var i=0; i570)?o[p]*0.8:o[p]+0.3*(255-o[p]);o[p]=parseInt(o[p],10)}this.highlightColors.push("rgb("+o[0]+","+o[1]+","+o[2]+")")}}this.highlightColorGenerator=new e.jqplot.ColorGenerator(this.highlightColors);u.postParseOptionsHooks.addOnce(m);u.postInitHooks.addOnce(g);u.eventListenerHooks.addOnce("jqplotMouseMove",b);u.eventListenerHooks.addOnce("jqplotMouseDown",a);u.eventListenerHooks.addOnce("jqplotMouseUp",l);u.eventListenerHooks.addOnce("jqplotClick",f);u.eventListenerHooks.addOnce("jqplotRightClick",n);u.postDrawHooks.addOnce(i)};e.jqplot.PieRenderer.prototype.setGridData=function(t){var p=[];var u=[];var o=this.startAngle/180*Math.PI;var s=0;this._drawData=false;for(var r=0;r0){p[r]+=p[r-1]}s+=this.data[r][1]}var q=Math.PI*2/p[p.length-1];for(var r=0;r0){p[r]+=p[r-1]}s+=t[r][1]}var q=Math.PI*2/p[p.length-1];for(var r=0;r0&&s>0.01&&s<6.282){w=parseFloat(p)/2/h(q)}return w}e.jqplot.PieRenderer.prototype.drawSlice=function(B,z,y,u,w){if(this._drawData){var p=this._radius;var A=this.fill;var x=this.lineWidth;var s=this.sliceMargin;if(this.fill==false){s+=this.lineWidth}B.save();B.translate(this._center[0],this._center[1]);var D=j(z,y,this.sliceMargin,this.fill,this.lineWidth);var o=D*Math.cos((z+y)/2);var C=D*Math.sin((z+y)/2);if((y-z)<=Math.PI){p-=D}else{p+=D}B.translate(o,C);if(w){for(var v=0,t=this.shadowDepth;v6.282+this.startAngle){y=6.282+this.startAngle;if(z>y){z=6.281+this.startAngle}}if(z>=y){return}B.beginPath();B.fillStyle=u;B.strokeStyle=u;B.lineWidth=x;B.arc(0,0,r,z,y,false);B.lineTo(0,0);B.closePath();if(A){B.fill()}else{B.stroke()}}};e.jqplot.PieRenderer.prototype.draw=function(B,z,E,o){var W;var H=(E!=undefined)?E:{};var t=0;var s=0;var N=1;var L=new e.jqplot.ColorGenerator(this.seriesColors);if(E.legendInfo&&E.legendInfo.placement=="insideGrid"){var J=E.legendInfo;switch(J.location){case"nw":t=J.width+J.xoffset;break;case"w":t=J.width+J.xoffset;break;case"sw":t=J.width+J.xoffset;break;case"ne":t=J.width+J.xoffset;N=-1;break;case"e":t=J.width+J.xoffset;N=-1;break;case"se":t=J.width+J.xoffset;N=-1;break;case"n":s=J.height+J.yoffset;break;case"s":s=J.height+J.yoffset;N=-1;break;default:break}}var K=(H.shadow!=undefined)?H.shadow:this.shadow;var A=(H.fill!=undefined)?H.fill:this.fill;var C=B.canvas.width;var I=B.canvas.height;var Q=C-t-2*this.padding;var X=I-s-2*this.padding;var M=Math.min(Q,X);var Y=M;this._sliceAngles=[];var v=this.sliceMargin;if(this.fill==false){v+=this.lineWidth}var q;var G=0;var R,aa,Z,ab;var D=this.startAngle/180*Math.PI;for(var W=0,V=z.length;WMath.PI){G=Math.max(q,G)}}if(this.diameter!=null&&this.diameter>0){this._diameter=this.diameter-2*G}else{this._diameter=Y-2*G}if(this._diameter<6){e.jqplot.log("Diameter of pie too small, not rendering.");return}var S=this._radius=this._diameter/2;this._center=[(C-N*t)/2+N*t+G*Math.cos(D),(I-N*s)/2+N*s+G*Math.sin(D)];if(this.shadow){for(var W=0,V=z.length;W=this.dataLabelThreshold){var F,U=(this._sliceAngles[W][0]+this._sliceAngles[W][1])/2,T;if(this.dataLabels=="label"){F=this.dataLabelFormatString||"%s";T=e.jqplot.sprintf(F,z[W][0])}else{if(this.dataLabels=="value"){F=this.dataLabelFormatString||"%d";T=e.jqplot.sprintf(F,this.data[W][1])}else{if(this.dataLabels=="percent"){F=this.dataLabelFormatString||"%d%%";T=e.jqplot.sprintf(F,z[W][2]*100)}else{if(this.dataLabels.constructor==Array){F=this.dataLabelFormatString||"%s";T=e.jqplot.sprintf(F,this.dataLabels[W])}}}}var p=(this._radius)*this.dataLabelPositionFactor+this.sliceMargin+this.dataLabelNudge;var P=this._center[0]+Math.cos(U)*p+this.canvas._offsets.left;var O=this._center[1]+Math.sin(U)*p+this.canvas._offsets.top;var u=e('
'+T+"
").insertBefore(o.eventCanvas._elem);if(this.dataLabelCenterOn){P-=u.width()/2;O-=u.height()/2}else{P-=u.width()*Math.sin(U/2);O-=u.height()/2}P=Math.round(P);O=Math.round(O);u.css({left:P,top:O})}}};e.jqplot.PieAxisRenderer=function(){e.jqplot.LinearAxisRenderer.call(this)};e.jqplot.PieAxisRenderer.prototype=new e.jqplot.LinearAxisRenderer();e.jqplot.PieAxisRenderer.prototype.constructor=e.jqplot.PieAxisRenderer;e.jqplot.PieAxisRenderer.prototype.init=function(o){this.tickRenderer=e.jqplot.PieTickRenderer;e.extend(true,this,o);this._dataBounds={min:0,max:100};this.min=0;this.max=100;this.showTicks=false;this.ticks=[];this.showMark=false;this.show=false};e.jqplot.PieLegendRenderer=function(){e.jqplot.TableLegendRenderer.call(this)};e.jqplot.PieLegendRenderer.prototype=new e.jqplot.TableLegendRenderer();e.jqplot.PieLegendRenderer.prototype.constructor=e.jqplot.PieLegendRenderer;e.jqplot.PieLegendRenderer.prototype.init=function(o){this.numberRows=null;this.numberColumns=null;e.extend(true,this,o)};e.jqplot.PieLegendRenderer.prototype.draw=function(){var r=this;if(this.show){var B=this._series;this._elem=e(document.createElement("table"));this._elem.addClass("jqplot-table-legend");var E={position:"absolute"};if(this.background){E.background=this.background}if(this.border){E.border=this.border}if(this.fontSize){E.fontSize=this.fontSize}if(this.fontFamily){E.fontFamily=this.fontFamily}if(this.textColor){E.textColor=this.textColor}if(this.marginTop!=null){E.marginTop=this.marginTop}if(this.marginBottom!=null){E.marginBottom=this.marginBottom}if(this.marginLeft!=null){E.marginLeft=this.marginLeft}if(this.marginRight!=null){E.marginRight=this.marginRight}this._elem.css(E);var I=false,A=false,o,y;var C=B[0];var p=new e.jqplot.ColorGenerator(C.seriesColors);if(C.show){var J=C.data;if(this.numberRows){o=this.numberRows;if(!this.numberColumns){y=Math.ceil(J.length/o)}else{y=this.numberColumns}}else{if(this.numberColumns){y=this.numberColumns;o=Math.ceil(J.length/this.numberColumns)}else{o=J.length;y=1}}var H,G;var q,w,v;var x,z,F;var D=0;var u,t;for(H=0;H0){I=true}else{I=false}}else{if(H==o-1){I=false}else{I=true}}z=(I)?this.rowSpacing:"0";w=e(document.createElement("td"));w.addClass("jqplot-table-legend jqplot-table-legend-swatch");w.css({textAlign:"center",paddingTop:z});u=e(document.createElement("div"));u.addClass("jqplot-table-legend-swatch-outline");t=e(document.createElement("div"));t.addClass("jqplot-table-legend-swatch");t.css({backgroundColor:F,borderColor:F});w.append(u.append(t));v=e(document.createElement("td"));v.addClass("jqplot-table-legend jqplot-table-legend-label");v.css("paddingTop",z);if(this.escapeHtml){v.text(x)}else{v.html(x)}if(A){v.prependTo(q);w.prependTo(q)}else{w.appendTo(q);v.appendTo(q)}I=true}D++}}}}return this._elem};e.jqplot.PieRenderer.prototype.handleMove=function(q,p,t,s,r){if(s){var o=[s.seriesIndex,s.pointIndex,s.data];r.target.trigger("jqplotDataMouseOver",o);if(r.series[o[0]].highlightMouseOver&&!(o[0]==r.plugins.pieRenderer.highlightedSeriesIndex&&o[1]==r.series[o[0]]._highlightedPoint)){r.target.trigger("jqplotDataHighlight",o);d(r,o[0],o[1])}}else{if(s==null){k(r)}}};function c(s,r,p){p=p||{};p.axesDefaults=p.axesDefaults||{};p.legend=p.legend||{};p.seriesDefaults=p.seriesDefaults||{};var o=false;if(p.seriesDefaults.renderer==e.jqplot.PieRenderer){o=true}else{if(p.series){for(var q=0;q 570 ? o[p] * 0.8 : o[p] + 0.3 * (255 - o[p]); + o[p] = parseInt(o[p], 10); + } + this.highlightColors.push( + "rgb(" + o[0] + "," + o[1] + "," + o[2] + ")", + ); + } + } + this.highlightColorGenerator = new e.jqplot.ColorGenerator( + this.highlightColors, + ); + u.postParseOptionsHooks.addOnce(m); + u.postInitHooks.addOnce(g); + u.eventListenerHooks.addOnce("jqplotMouseMove", b); + u.eventListenerHooks.addOnce("jqplotMouseDown", a); + u.eventListenerHooks.addOnce("jqplotMouseUp", l); + u.eventListenerHooks.addOnce("jqplotClick", f); + u.eventListenerHooks.addOnce("jqplotRightClick", n); + u.postDrawHooks.addOnce(i); + }; + e.jqplot.PieRenderer.prototype.setGridData = function (t) { + var p = []; + var u = []; + var o = (this.startAngle / 180) * Math.PI; + var s = 0; + this._drawData = false; + for (var r = 0; r < this.data.length; r++) { + if (this.data[r][1] != 0) { + this._drawData = true; + } + p.push(this.data[r][1]); + u.push([this.data[r][0]]); + if (r > 0) { + p[r] += p[r - 1]; + } + s += this.data[r][1]; + } + var q = (Math.PI * 2) / p[p.length - 1]; + for (var r = 0; r < p.length; r++) { + u[r][1] = p[r] * q; + u[r][2] = this.data[r][1] / s; + } + this.gridData = u; + }; + e.jqplot.PieRenderer.prototype.makeGridData = function (t, u) { + var p = []; + var v = []; + var s = 0; + var o = (this.startAngle / 180) * Math.PI; + this._drawData = false; + for (var r = 0; r < t.length; r++) { + if (this.data[r][1] != 0) { + this._drawData = true; + } + p.push(t[r][1]); + v.push([t[r][0]]); + if (r > 0) { + p[r] += p[r - 1]; + } + s += t[r][1]; + } + var q = (Math.PI * 2) / p[p.length - 1]; + for (var r = 0; r < p.length; r++) { + v[r][1] = p[r] * q; + v[r][2] = t[r][1] / s; + } + return v; + }; + function h(o) { + return Math.sin((o - (o - Math.PI) / 8 / Math.PI) / 2); + } + function j(u, t, o, v, r) { + var w = 0; + var q = t - u; + var s = Math.abs(q); + var p = o; + if (v == false) { + p += r; + } + if (p > 0 && s > 0.01 && s < 6.282) { + w = parseFloat(p) / 2 / h(q); + } + return w; + } + e.jqplot.PieRenderer.prototype.drawSlice = function (B, z, y, u, w) { + if (this._drawData) { + var p = this._radius; + var A = this.fill; + var x = this.lineWidth; + var s = this.sliceMargin; + if (this.fill == false) { + s += this.lineWidth; + } + B.save(); + B.translate(this._center[0], this._center[1]); + var D = j(z, y, this.sliceMargin, this.fill, this.lineWidth); + var o = D * Math.cos((z + y) / 2); + var C = D * Math.sin((z + y) / 2); + if (y - z <= Math.PI) { + p -= D; + } else { + p += D; + } + B.translate(o, C); + if (w) { + for (var v = 0, t = this.shadowDepth; v < t; v++) { + B.save(); + B.translate( + this.shadowOffset * + Math.cos((this.shadowAngle / 180) * Math.PI), + this.shadowOffset * + Math.sin((this.shadowAngle / 180) * Math.PI), + ); + q(p); + } + for (var v = 0, t = this.shadowDepth; v < t; v++) { + B.restore(); + } + } else { + q(p); + } + B.restore(); + } + function q(r) { + if (y > 6.282 + this.startAngle) { + y = 6.282 + this.startAngle; + if (z > y) { + z = 6.281 + this.startAngle; + } + } + if (z >= y) { + return; + } + B.beginPath(); + B.fillStyle = u; + B.strokeStyle = u; + B.lineWidth = x; + B.arc(0, 0, r, z, y, false); + B.lineTo(0, 0); + B.closePath(); + if (A) { + B.fill(); + } else { + B.stroke(); + } + } + }; + e.jqplot.PieRenderer.prototype.draw = function (B, z, E, o) { + var W; + var H = E != undefined ? E : {}; + var t = 0; + var s = 0; + var N = 1; + var L = new e.jqplot.ColorGenerator(this.seriesColors); + if (E.legendInfo && E.legendInfo.placement == "insideGrid") { + var J = E.legendInfo; + switch (J.location) { + case "nw": + t = J.width + J.xoffset; + break; + case "w": + t = J.width + J.xoffset; + break; + case "sw": + t = J.width + J.xoffset; + break; + case "ne": + t = J.width + J.xoffset; + N = -1; + break; + case "e": + t = J.width + J.xoffset; + N = -1; + break; + case "se": + t = J.width + J.xoffset; + N = -1; + break; + case "n": + s = J.height + J.yoffset; + break; + case "s": + s = J.height + J.yoffset; + N = -1; + break; + default: + break; + } + } + var K = H.shadow != undefined ? H.shadow : this.shadow; + var A = H.fill != undefined ? H.fill : this.fill; + var C = B.canvas.width; + var I = B.canvas.height; + var Q = C - t - 2 * this.padding; + var X = I - s - 2 * this.padding; + var M = Math.min(Q, X); + var Y = M; + this._sliceAngles = []; + var v = this.sliceMargin; + if (this.fill == false) { + v += this.lineWidth; + } + var q; + var G = 0; + var R, aa, Z, ab; + var D = (this.startAngle / 180) * Math.PI; + for (var W = 0, V = z.length; W < V; W++) { + aa = W == 0 ? D : z[W - 1][1] + D; + Z = z[W][1] + D; + this._sliceAngles.push([aa, Z]); + q = j(aa, Z, this.sliceMargin, this.fill, this.lineWidth); + if (Math.abs(Z - aa) > Math.PI) { + G = Math.max(q, G); + } + } + if (this.diameter != null && this.diameter > 0) { + this._diameter = this.diameter - 2 * G; + } else { + this._diameter = Y - 2 * G; + } + if (this._diameter < 6) { + e.jqplot.log("Diameter of pie too small, not rendering."); + return; + } + var S = (this._radius = this._diameter / 2); + this._center = [ + (C - N * t) / 2 + N * t + G * Math.cos(D), + (I - N * s) / 2 + N * s + G * Math.sin(D), + ]; + if (this.shadow) { + for (var W = 0, V = z.length; W < V; W++) { + ab = "rgba(0,0,0," + this.shadowAlpha + ")"; + this.renderer.drawSlice.call( + this, + B, + this._sliceAngles[W][0], + this._sliceAngles[W][1], + ab, + true, + ); + } + } + for (var W = 0; W < z.length; W++) { + this.renderer.drawSlice.call( + this, + B, + this._sliceAngles[W][0], + this._sliceAngles[W][1], + L.next(), + false, + ); + if ( + this.showDataLabels && + z[W][2] * 100 >= this.dataLabelThreshold + ) { + var F, + U = (this._sliceAngles[W][0] + this._sliceAngles[W][1]) / 2, + T; + if (this.dataLabels == "label") { + F = this.dataLabelFormatString || "%s"; + T = e.jqplot.sprintf(F, z[W][0]); + } else { + if (this.dataLabels == "value") { + F = this.dataLabelFormatString || "%d"; + T = e.jqplot.sprintf(F, this.data[W][1]); + } else { + if (this.dataLabels == "percent") { + F = this.dataLabelFormatString || "%d%%"; + T = e.jqplot.sprintf(F, z[W][2] * 100); + } else { + if (this.dataLabels.constructor == Array) { + F = this.dataLabelFormatString || "%s"; + T = e.jqplot.sprintf(F, this.dataLabels[W]); + } + } + } + } + var p = + this._radius * this.dataLabelPositionFactor + + this.sliceMargin + + this.dataLabelNudge; + var P = + this._center[0] + + Math.cos(U) * p + + this.canvas._offsets.left; + var O = + this._center[1] + + Math.sin(U) * p + + this.canvas._offsets.top; + var u = e( + '
' + + T + + "
", + ).insertBefore(o.eventCanvas._elem); + if (this.dataLabelCenterOn) { + P -= u.width() / 2; + O -= u.height() / 2; + } else { + P -= u.width() * Math.sin(U / 2); + O -= u.height() / 2; + } + P = Math.round(P); + O = Math.round(O); + u.css({ left: P, top: O }); + } + } + }; + e.jqplot.PieAxisRenderer = function () { + e.jqplot.LinearAxisRenderer.call(this); + }; + e.jqplot.PieAxisRenderer.prototype = new e.jqplot.LinearAxisRenderer(); + e.jqplot.PieAxisRenderer.prototype.constructor = e.jqplot.PieAxisRenderer; + e.jqplot.PieAxisRenderer.prototype.init = function (o) { + this.tickRenderer = e.jqplot.PieTickRenderer; + e.extend(true, this, o); + this._dataBounds = { min: 0, max: 100 }; + this.min = 0; + this.max = 100; + this.showTicks = false; + this.ticks = []; + this.showMark = false; + this.show = false; + }; + e.jqplot.PieLegendRenderer = function () { + e.jqplot.TableLegendRenderer.call(this); + }; + e.jqplot.PieLegendRenderer.prototype = new e.jqplot.TableLegendRenderer(); + e.jqplot.PieLegendRenderer.prototype.constructor = + e.jqplot.PieLegendRenderer; + e.jqplot.PieLegendRenderer.prototype.init = function (o) { + this.numberRows = null; + this.numberColumns = null; + e.extend(true, this, o); + }; + e.jqplot.PieLegendRenderer.prototype.draw = function () { + var r = this; + if (this.show) { + var B = this._series; + this._elem = e(document.createElement("table")); + this._elem.addClass("jqplot-table-legend"); + var E = { position: "absolute" }; + if (this.background) { + E.background = this.background; + } + if (this.border) { + E.border = this.border; + } + if (this.fontSize) { + E.fontSize = this.fontSize; + } + if (this.fontFamily) { + E.fontFamily = this.fontFamily; + } + if (this.textColor) { + E.textColor = this.textColor; + } + if (this.marginTop != null) { + E.marginTop = this.marginTop; + } + if (this.marginBottom != null) { + E.marginBottom = this.marginBottom; + } + if (this.marginLeft != null) { + E.marginLeft = this.marginLeft; + } + if (this.marginRight != null) { + E.marginRight = this.marginRight; + } + this._elem.css(E); + var I = false, + A = false, + o, + y; + var C = B[0]; + var p = new e.jqplot.ColorGenerator(C.seriesColors); + if (C.show) { + var J = C.data; + if (this.numberRows) { + o = this.numberRows; + if (!this.numberColumns) { + y = Math.ceil(J.length / o); + } else { + y = this.numberColumns; + } + } else { + if (this.numberColumns) { + y = this.numberColumns; + o = Math.ceil(J.length / this.numberColumns); + } else { + o = J.length; + y = 1; + } + } + var H, G; + var q, w, v; + var x, z, F; + var D = 0; + var u, t; + for (H = 0; H < o; H++) { + q = e(document.createElement("tr")); + q.addClass("jqplot-table-legend"); + if (A) { + q.prependTo(this._elem); + } else { + q.appendTo(this._elem); + } + for (G = 0; G < y; G++) { + if (D < J.length) { + x = this.labels[D] || J[D][0].toString(); + F = p.next(); + if (!A) { + if (H > 0) { + I = true; + } else { + I = false; + } + } else { + if (H == o - 1) { + I = false; + } else { + I = true; + } + } + z = I ? this.rowSpacing : "0"; + w = e(document.createElement("td")); + w.addClass( + "jqplot-table-legend jqplot-table-legend-swatch", + ); + w.css({ textAlign: "center", paddingTop: z }); + u = e(document.createElement("div")); + u.addClass("jqplot-table-legend-swatch-outline"); + t = e(document.createElement("div")); + t.addClass("jqplot-table-legend-swatch"); + t.css({ backgroundColor: F, borderColor: F }); + w.append(u.append(t)); + v = e(document.createElement("td")); + v.addClass( + "jqplot-table-legend jqplot-table-legend-label", + ); + v.css("paddingTop", z); + if (this.escapeHtml) { + v.text(x); + } else { + v.html(x); + } + if (A) { + v.prependTo(q); + w.prependTo(q); + } else { + w.appendTo(q); + v.appendTo(q); + } + I = true; + } + D++; + } + } + } + } + return this._elem; + }; + e.jqplot.PieRenderer.prototype.handleMove = function (q, p, t, s, r) { + if (s) { + var o = [s.seriesIndex, s.pointIndex, s.data]; + r.target.trigger("jqplotDataMouseOver", o); + if ( + r.series[o[0]].highlightMouseOver && + !( + o[0] == r.plugins.pieRenderer.highlightedSeriesIndex && + o[1] == r.series[o[0]]._highlightedPoint + ) + ) { + r.target.trigger("jqplotDataHighlight", o); + d(r, o[0], o[1]); + } + } else { + if (s == null) { + k(r); + } + } + }; + function c(s, r, p) { + p = p || {}; + p.axesDefaults = p.axesDefaults || {}; + p.legend = p.legend || {}; + p.seriesDefaults = p.seriesDefaults || {}; + var o = false; + if (p.seriesDefaults.renderer == e.jqplot.PieRenderer) { + o = true; + } else { + if (p.series) { + for (var q = 0; q < p.series.length; q++) { + if (p.series[q].renderer == e.jqplot.PieRenderer) { + o = true; + } + } + } + } + if (o) { + p.axesDefaults.renderer = e.jqplot.PieAxisRenderer; + p.legend.renderer = e.jqplot.PieLegendRenderer; + p.legend.preDraw = true; + p.seriesDefaults.pointLabels = { show: false }; + } + } + function g(r, q, o) { + for (var p = 0; p < this.series.length; p++) { + if (this.series[p].renderer.constructor == e.jqplot.PieRenderer) { + if (this.series[p].highlightMouseOver) { + this.series[p].highlightMouseDown = false; + } + } + } + } + function m(o) { + for (var p = 0; p < this.series.length; p++) { + this.series[p].seriesColors = this.seriesColors; + this.series[p].colorGenerator = e.jqplot.colorGenerator; + } + } + function d(t, r, q) { + var p = t.series[r]; + var o = t.plugins.pieRenderer.highlightCanvas; + o._ctx.clearRect(0, 0, o._ctx.canvas.width, o._ctx.canvas.height); + p._highlightedPoint = q; + t.plugins.pieRenderer.highlightedSeriesIndex = r; + p.renderer.drawSlice.call( + p, + o._ctx, + p._sliceAngles[q][0], + p._sliceAngles[q][1], + p.highlightColorGenerator.get(q), + false, + ); + } + function k(q) { + var o = q.plugins.pieRenderer.highlightCanvas; + o._ctx.clearRect(0, 0, o._ctx.canvas.width, o._ctx.canvas.height); + for (var p = 0; p < q.series.length; p++) { + q.series[p]._highlightedPoint = null; + } + q.plugins.pieRenderer.highlightedSeriesIndex = null; + q.target.trigger("jqplotDataUnhighlight"); + } + function b(s, r, v, u, t) { + if (u) { + var q = [u.seriesIndex, u.pointIndex, u.data]; + var p = jQuery.Event("jqplotDataMouseOver"); + p.pageX = s.pageX; + p.pageY = s.pageY; + t.target.trigger(p, q); + if ( + t.series[q[0]].highlightMouseOver && + !( + q[0] == t.plugins.pieRenderer.highlightedSeriesIndex && + q[1] == t.series[q[0]]._highlightedPoint + ) + ) { + var o = jQuery.Event("jqplotDataHighlight"); + o.which = s.which; + o.pageX = s.pageX; + o.pageY = s.pageY; + t.target.trigger(o, q); + d(t, q[0], q[1]); + } + } else { + if (u == null) { + k(t); + } + } + } + function a(r, q, u, t, s) { + if (t) { + var p = [t.seriesIndex, t.pointIndex, t.data]; + if ( + s.series[p[0]].highlightMouseDown && + !( + p[0] == s.plugins.pieRenderer.highlightedSeriesIndex && + p[1] == s.series[p[0]]._highlightedPoint + ) + ) { + var o = jQuery.Event("jqplotDataHighlight"); + o.which = r.which; + o.pageX = r.pageX; + o.pageY = r.pageY; + s.target.trigger(o, p); + d(s, p[0], p[1]); + } + } else { + if (t == null) { + k(s); + } + } + } + function l(q, p, t, s, r) { + var o = r.plugins.pieRenderer.highlightedSeriesIndex; + if (o != null && r.series[o].highlightMouseDown) { + k(r); + } + } + function f(r, q, u, t, s) { + if (t) { + var p = [t.seriesIndex, t.pointIndex, t.data]; + var o = jQuery.Event("jqplotDataClick"); + o.which = r.which; + o.pageX = r.pageX; + o.pageY = r.pageY; + s.target.trigger(o, p); + } + } + function n(s, r, v, u, t) { + if (u) { + var q = [u.seriesIndex, u.pointIndex, u.data]; + var o = t.plugins.pieRenderer.highlightedSeriesIndex; + if (o != null && t.series[o].highlightMouseDown) { + k(t); + } + var p = jQuery.Event("jqplotDataRightClick"); + p.which = s.which; + p.pageX = s.pageX; + p.pageY = s.pageY; + t.target.trigger(p, q); + } + } + function i() { + if ( + this.plugins.pieRenderer && + this.plugins.pieRenderer.highlightCanvas + ) { + this.plugins.pieRenderer.highlightCanvas.resetCanvas(); + this.plugins.pieRenderer.highlightCanvas = null; + } + this.plugins.pieRenderer = { highlightedSeriesIndex: null }; + this.plugins.pieRenderer.highlightCanvas = new e.jqplot.GenericCanvas(); + var p = e(this.targetId + " .jqplot-data-label"); + if (p.length) { + e(p[0]).before( + this.plugins.pieRenderer.highlightCanvas.createElement( + this._gridPadding, + "jqplot-pieRenderer-highlight-canvas", + this._plotDimensions, + this, + ), + ); + } else { + this.eventCanvas._elem.before( + this.plugins.pieRenderer.highlightCanvas.createElement( + this._gridPadding, + "jqplot-pieRenderer-highlight-canvas", + this._plotDimensions, + this, + ), + ); + } + var o = this.plugins.pieRenderer.highlightCanvas.setContext(); + this.eventCanvas._elem.bind("mouseleave", { plot: this }, function (q) { + k(q.data.plot); + }); + } + e.jqplot.preInitHooks.push(c); + e.jqplot.PieTickRenderer = function () { + e.jqplot.AxisTickRenderer.call(this); + }; + e.jqplot.PieTickRenderer.prototype = new e.jqplot.AxisTickRenderer(); + e.jqplot.PieTickRenderer.prototype.constructor = e.jqplot.PieTickRenderer; +})(jQuery); diff --git a/src/adminactions/static/adminactions/js/massupdate.js b/src/adminactions/static/adminactions/js/massupdate.js index 67b6a0b7..1890ce84 100644 --- a/src/adminactions/static/adminactions/js/massupdate.js +++ b/src/adminactions/static/adminactions/js/massupdate.js @@ -1,46 +1,74 @@ - "use strict"; +"use strict"; (function ($) { $(function () { - $('.func_select').change(function () { - var $option = $(this).find(':selected'); - var target = $(this).parent().parent().find('.col_field input, .col_field select .col_field textarea'); - if ($option.hasClass('noparam')) { - $(target).attr('disabled', 'disabled'); + $(".func_select").change(function () { + var $option = $(this).find(":selected"); + var target = $(this) + .parent() + .parent() + .find( + ".col_field input, .col_field select .col_field textarea", + ); + if ($option.hasClass("noparam")) { + $(target).attr("disabled", "disabled"); } else { - $(target).removeAttr('disabled'); + $(target).removeAttr("disabled"); } }); - $('.col_field input, .col_field select, .col_field textarea, .col_func select').each(function () { - if (!$(this).parent().parent().find('.col_enabler input[type=checkbox]').is(':checked')) { - $(this).attr('disabled', 'disabled'); + $( + ".col_field input, .col_field select, .col_field textarea, .col_func select", + ).each(function () { + if ( + !$(this) + .parent() + .parent() + .find(".col_enabler input[type=checkbox]") + .is(":checked") + ) { + $(this).attr("disabled", "disabled"); } }); - $('.fastfieldvalue').click(function () { - var check = $(this).parent().parent().find('.enabler'); - var selection = $(this).data('value'); - $(check).attr('checked', true); - var target = $(this).parent().parent().find('.col_field input, .col_field select, .col_field textarea').not('.enabler'); - $(this).parent().parent().find('.col_func select').removeAttr('disabled'); - $(target).removeAttr('disabled'); - if ($(target).is('select')) { - $('option', target).each(function (i, selected) { + $(".fastfieldvalue").click(function () { + var check = $(this).parent().parent().find(".enabler"); + var selection = $(this).data("value"); + $(check).attr("checked", true); + var target = $(this) + .parent() + .parent() + .find( + ".col_field input, .col_field select, .col_field textarea", + ) + .not(".enabler"); + $(this) + .parent() + .parent() + .find(".col_func select") + .removeAttr("disabled"); + $(target).removeAttr("disabled"); + if ($(target).is("select")) { + $("option", target).each(function (i, selected) { if ($(this).val().toString() === selection.toString()) { - $(this).attr('selected', true); + $(this).attr("selected", true); } }); - } else if ($(target).is('input[type=checkbox]')) { - $(target).attr('checked', selection === 'True'); + } else if ($(target).is("input[type=checkbox]")) { + $(target).attr("checked", selection === "True"); } else { $(target).val(selection); } }); - $('.enabler').click(function () { - var target = $(this).parent().parent().find('.col_field input, .col_field select, .col_field textarea, .col_func select'); - if ($(this).is(':checked')) { - $(target).removeAttr('disabled'); + $(".enabler").click(function () { + var target = $(this) + .parent() + .parent() + .find( + ".col_field input, .col_field select, .col_field textarea, .col_func select", + ); + if ($(this).is(":checked")) { + $(target).removeAttr("disabled"); } else { - $(target).attr('disabled', 'disabled'); + $(target).attr("disabled", "disabled"); } - }) + }); }); })(django.jQuery); diff --git a/src/adminactions/static/adminactions/js/massupdate.min.js b/src/adminactions/static/adminactions/js/massupdate.min.js index 7332580d..1890ce84 100644 --- a/src/adminactions/static/adminactions/js/massupdate.min.js +++ b/src/adminactions/static/adminactions/js/massupdate.min.js @@ -1 +1,74 @@ -"use strict";(function($){$(function(){$(".func_select").change(function(){var $option=$(this).find(":selected");var target=$(this).parent().parent().find(".col_field input, .col_field select .col_field textarea");if($option.hasClass("noparam")){$(target).attr("disabled","disabled")}else{$(target).removeAttr("disabled")}});$(".col_field input, .col_field select, .col_field textarea, .col_func select").each(function(){if(!$(this).parent().parent().find(".col_enabler input[type=checkbox]").is(":checked")){$(this).attr("disabled","disabled")}});$(".fastfieldvalue").click(function(){var check=$(this).parent().parent().find(".enabler");var selection=$(this).data("value");$(check).attr("checked",true);var target=$(this).parent().parent().find(".col_field input, .col_field select, .col_field textarea").not(".enabler");$(this).parent().parent().find(".col_func select").removeAttr("disabled");$(target).removeAttr("disabled");if($(target).is("select")){$("option",target).each(function(i,selected){if($(this).val().toString()===selection.toString()){$(this).attr("selected",true)}})}else if($(target).is("input[type=checkbox]")){$(target).attr("checked",selection==="True")}else{$(target).val(selection)}});$(".enabler").click(function(){var target=$(this).parent().parent().find(".col_field input, .col_field select, .col_field textarea, .col_func select");if($(this).is(":checked")){$(target).removeAttr("disabled")}else{$(target).attr("disabled","disabled")}})})})(django.jQuery); \ No newline at end of file +"use strict"; +(function ($) { + $(function () { + $(".func_select").change(function () { + var $option = $(this).find(":selected"); + var target = $(this) + .parent() + .parent() + .find( + ".col_field input, .col_field select .col_field textarea", + ); + if ($option.hasClass("noparam")) { + $(target).attr("disabled", "disabled"); + } else { + $(target).removeAttr("disabled"); + } + }); + $( + ".col_field input, .col_field select, .col_field textarea, .col_func select", + ).each(function () { + if ( + !$(this) + .parent() + .parent() + .find(".col_enabler input[type=checkbox]") + .is(":checked") + ) { + $(this).attr("disabled", "disabled"); + } + }); + $(".fastfieldvalue").click(function () { + var check = $(this).parent().parent().find(".enabler"); + var selection = $(this).data("value"); + $(check).attr("checked", true); + var target = $(this) + .parent() + .parent() + .find( + ".col_field input, .col_field select, .col_field textarea", + ) + .not(".enabler"); + $(this) + .parent() + .parent() + .find(".col_func select") + .removeAttr("disabled"); + $(target).removeAttr("disabled"); + if ($(target).is("select")) { + $("option", target).each(function (i, selected) { + if ($(this).val().toString() === selection.toString()) { + $(this).attr("selected", true); + } + }); + } else if ($(target).is("input[type=checkbox]")) { + $(target).attr("checked", selection === "True"); + } else { + $(target).val(selection); + } + }); + $(".enabler").click(function () { + var target = $(this) + .parent() + .parent() + .find( + ".col_field input, .col_field select, .col_field textarea, .col_func select", + ); + if ($(this).is(":checked")) { + $(target).removeAttr("disabled"); + } else { + $(target).attr("disabled", "disabled"); + } + }); + }); +})(django.jQuery); diff --git a/src/adminactions/static/adminactions/js/merge.js b/src/adminactions/static/adminactions/js/merge.js index bceaba6e..0616ba6c 100644 --- a/src/adminactions/static/adminactions/js/merge.js +++ b/src/adminactions/static/adminactions/js/merge.js @@ -1,68 +1,84 @@ (function ($) { $(function () { var select = function (from) { - return function ( event ) { + return function (event) { event.preventDefault(); var $row = $(this).parent().parent(); var $sel = $row.find(from); - $('.result input', $row).val($('input.raw-value', $sel).val()); + $(".result input", $row).val($("input.raw-value", $sel).val()); highlight(); }; }; var highlight = function () { var RIGHT = []; - $('.mergetable tr.merge-row').each(function () { + $(".mergetable tr.merge-row").each(function () { + var $result = $(this).find("td.result"); + var $left = $(this).find("td.origin"); + var $right = $(this).find("td.other"); + var field_name = $(this).find("td:first").attr("data-content"); - var $result = $(this).find('td.result'); - var $left = $(this).find('td.origin'); - var $right = $(this).find('td.other'); - var field_name = $(this).find('td:first').attr('data-content'); + $("td", this).removeClass("selected"); - $('td', this).removeClass("selected"); - - if ($('input.raw-value', $right).val() === $('input.raw-value', $left).val()) { - $('p.display', $result).text($('p.display', $left).text()); - } else if ($('input.raw-value', $result).val() === $('input.raw-value', $left).val()) { - $(this).find('td.origin').addClass("selected"); - $('p.display', $result).text($('p.display', $left).text()); - } else if ($('input.raw-value', $result).val() === $('input.raw-value', $right).val()) { - $(this).find('td.other').addClass("selected"); - $('p.display', $result).text($('p.display', $right).text()); + if ( + $("input.raw-value", $right).val() === + $("input.raw-value", $left).val() + ) { + $("p.display", $result).text($("p.display", $left).text()); + } else if ( + $("input.raw-value", $result).val() === + $("input.raw-value", $left).val() + ) { + $(this).find("td.origin").addClass("selected"); + $("p.display", $result).text($("p.display", $left).text()); + } else if ( + $("input.raw-value", $result).val() === + $("input.raw-value", $right).val() + ) { + $(this).find("td.other").addClass("selected"); + $("p.display", $result).text($("p.display", $right).text()); RIGHT.push(field_name); } - $('input[name=field_names]').val(RIGHT); + $("input[name=field_names]").val(RIGHT); }); - $('.mergetable tr.preview-row').each(function () { - - var $result = $(this).find('td.result'); - var $left = $(this).find('td.origin'); - var $right = $(this).find('td.other'); - var field_name = $(this).find('td:first').attr('data-content'); + $(".mergetable tr.preview-row").each(function () { + var $result = $(this).find("td.result"); + var $left = $(this).find("td.origin"); + var $right = $(this).find("td.other"); + var field_name = $(this).find("td:first").attr("data-content"); - $('td', this).removeClass("selected"); + $("td", this).removeClass("selected"); - if ($('.original .display', this).text() !== $('.result .display', this).text()){ + if ( + $(".original .display", this).text() !== + $(".result .display", this).text() + ) { $(this).addClass("changed"); } }); }; - $('a.origin').click(select("td.origin")); - $('a.other').click(select("td.other")); + $("a.origin").click(select("td.origin")); + $("a.other").click(select("td.other")); - $('a.swap').click(function ( event ) { + $("a.swap").click(function (event) { event.preventDefault(); var left = []; var right = []; var $master = $('input[name="master_pk"]'); var $other = $('input[name="other_pk"]'); - $('.column.origin').each(function () { - left.push([$('input.raw-value', this).val(), $('.display', this).text()]); + $(".column.origin").each(function () { + left.push([ + $("input.raw-value", this).val(), + $(".display", this).text(), + ]); }); - $('.column.other').each(function () { - right.push([$('input.raw-value', this).val(), $('.display', this).text()]); + $(".column.other").each(function () { + right.push([ + $("input.raw-value", this).val(), + $(".display", this).text(), + ]); }); left.push($master.val()); @@ -74,15 +90,15 @@ $('span[id="master_pk"]').text($master.val()); $('span[id="other_pk"]').text($other.val()); - $($('.column.origin').get().reverse()).each(function () { + $($(".column.origin").get().reverse()).each(function () { var entry = right.pop(); - $('input.raw-value', this).val(entry[0]); - $('.display', this).text(entry[1]); + $("input.raw-value", this).val(entry[0]); + $(".display", this).text(entry[1]); }); - $($('.column.other').get().reverse()).each(function () { + $($(".column.other").get().reverse()).each(function () { var entry = left.pop(); - $('input.raw-value', this).val(entry[0]); - $('.display', this).text(entry[1]); + $("input.raw-value", this).val(entry[0]); + $(".display", this).text(entry[1]); }); highlight(); }); diff --git a/src/adminactions/static/adminactions/js/merge.min.js b/src/adminactions/static/adminactions/js/merge.min.js index 98194325..f9a9d067 100644 --- a/src/adminactions/static/adminactions/js/merge.min.js +++ b/src/adminactions/static/adminactions/js/merge.min.js @@ -1 +1,95 @@ -(function($){$(function(){var select=function(from){return function(event){event.preventDefault();var $row=$(this).parent().parent();var $sel=$row.find(from);$(".result input",$row).val($("input.raw-value",$sel).val());highlight()}};var highlight=function(){var RIGHT=[];$(".mergetable tr.merge-row").each(function(){var $result=$(this).find("td.result");var $left=$(this).find("td.origin");var $right=$(this).find("td.other");var field_name=$(this).find("td:first").attr("data-content");$("td",this).removeClass("selected");if($("input.raw-value",$right).val()===$("input.raw-value",$left).val()){$("p.display",$result).text($("p.display",$left).text())}else if($("input.raw-value",$result).val()===$("input.raw-value",$left).val()){$(this).find("td.origin").addClass("selected");$("p.display",$result).text($("p.display",$left).text())}else if($("input.raw-value",$result).val()===$("input.raw-value",$right).val()){$(this).find("td.other").addClass("selected");$("p.display",$result).text($("p.display",$right).text());RIGHT.push(field_name)}$("input[name=field_names]").val(RIGHT)});$(".mergetable tr.preview-row").each(function(){var $result=$(this).find("td.result");var $left=$(this).find("td.origin");var $right=$(this).find("td.other");var field_name=$(this).find("td:first").attr("data-content");$("td",this).removeClass("selected");if($(".original .display",this).text()!==$(".result .display",this).text()){$(this).addClass("changed")}})};$("a.origin").click(select("td.origin"));$("a.other").click(select("td.other"));$("a.swap").click(function(event){event.preventDefault();var left=[];var right=[];var $master=$('input[name="master_pk"]');var $other=$('input[name="other_pk"]');$(".column.origin").each(function(){left.push([$("input.raw-value",this).val(),$(".display",this).text()])});$(".column.other").each(function(){right.push([$("input.raw-value",this).val(),$(".display",this).text()])});left.push($master.val());right.push($other.val());$master.val(right.pop());$other.val(left.pop());$('span[id="master_pk"]').text($master.val());$('span[id="other_pk"]').text($other.val());$($(".column.origin").get().reverse()).each(function(){var entry=right.pop();$("input.raw-value",this).val(entry[0]);$(".display",this).text(entry[1])});$($(".column.other").get().reverse()).each(function(){var entry=left.pop();$("input.raw-value",this).val(entry[0]);$(".display",this).text(entry[1])});highlight()});highlight()})})(django.jQuery); \ No newline at end of file +(function ($) { + $(function () { + var select = function (from) { + return function (event) { + event.preventDefault(); + var $row = $(this).parent().parent(); + var $sel = $row.find(from); + $(".result input", $row).val($("input.raw-value", $sel).val()); + highlight(); + }; + }; + var highlight = function () { + var RIGHT = []; + $(".mergetable tr.merge-row").each(function () { + var $result = $(this).find("td.result"); + var $left = $(this).find("td.origin"); + var $right = $(this).find("td.other"); + var field_name = $(this).find("td:first").attr("data-content"); + $("td", this).removeClass("selected"); + if ( + $("input.raw-value", $right).val() === + $("input.raw-value", $left).val() + ) { + $("p.display", $result).text($("p.display", $left).text()); + } else if ( + $("input.raw-value", $result).val() === + $("input.raw-value", $left).val() + ) { + $(this).find("td.origin").addClass("selected"); + $("p.display", $result).text($("p.display", $left).text()); + } else if ( + $("input.raw-value", $result).val() === + $("input.raw-value", $right).val() + ) { + $(this).find("td.other").addClass("selected"); + $("p.display", $result).text($("p.display", $right).text()); + RIGHT.push(field_name); + } + $("input[name=field_names]").val(RIGHT); + }); + $(".mergetable tr.preview-row").each(function () { + var $result = $(this).find("td.result"); + var $left = $(this).find("td.origin"); + var $right = $(this).find("td.other"); + var field_name = $(this).find("td:first").attr("data-content"); + $("td", this).removeClass("selected"); + if ( + $(".original .display", this).text() !== + $(".result .display", this).text() + ) { + $(this).addClass("changed"); + } + }); + }; + $("a.origin").click(select("td.origin")); + $("a.other").click(select("td.other")); + $("a.swap").click(function (event) { + event.preventDefault(); + var left = []; + var right = []; + var $master = $('input[name="master_pk"]'); + var $other = $('input[name="other_pk"]'); + $(".column.origin").each(function () { + left.push([ + $("input.raw-value", this).val(), + $(".display", this).text(), + ]); + }); + $(".column.other").each(function () { + right.push([ + $("input.raw-value", this).val(), + $(".display", this).text(), + ]); + }); + left.push($master.val()); + right.push($other.val()); + $master.val(right.pop()); + $other.val(left.pop()); + $('span[id="master_pk"]').text($master.val()); + $('span[id="other_pk"]').text($other.val()); + $($(".column.origin").get().reverse()).each(function () { + var entry = right.pop(); + $("input.raw-value", this).val(entry[0]); + $(".display", this).text(entry[1]); + }); + $($(".column.other").get().reverse()).each(function () { + var entry = left.pop(); + $("input.raw-value", this).val(entry[0]); + $(".display", this).text(entry[1]); + }); + highlight(); + }); + highlight(); + }); +})(django.jQuery); diff --git a/src/adminactions/tasks.py b/src/adminactions/tasks.py index 2f578fea..bdf04218 100644 --- a/src/adminactions/tasks.py +++ b/src/adminactions/tasks.py @@ -1,13 +1,17 @@ import logging +from typing import Any from celery import shared_task # noqa from django.apps import apps +from django.db.models.base import Model logger = logging.getLogger(__name__) @shared_task() -def mass_update_task(model, ids, rules, validate, clean, user_pk): +def mass_update_task( + model: Model, ids: list[Any], rules: dict[str, tuple[callable, Any]], validate: bool, clean: bool, user_pk: Any +) -> None: from adminactions.mass_update import mass_update_execute try: diff --git a/src/adminactions/templates/500.html b/src/adminactions/templates/500.html index bd9b6e65..89a80883 100644 --- a/src/adminactions/templates/500.html +++ b/src/adminactions/templates/500.html @@ -1,10 +1,7 @@ - + - + - - - - + + diff --git a/src/adminactions/templates/adminactions/any_model.html b/src/adminactions/templates/adminactions/any_model.html index d3776a98..567d53d5 100644 --- a/src/adminactions/templates/adminactions/any_model.html +++ b/src/adminactions/templates/adminactions/any_model.html @@ -1,5 +1,5 @@ {% extends "admin/change_form.html" %} -{% load i18n admin_modify static %} +{% load admin_modify i18n static %} {% block extrahead %}{{ block.super }} - - -{% endblock %} - -{% block breadcrumbs %}{% if not is_popup %} - -{% endif %}{% endblock %} - -{% block content %} - {% if formset.errors %} -

- {% if formset.errors|length == 1 %}{% trans "Please correct the error below." %}{% else %}{% trans "Please correct the errors below." %}{% endif %} -

- {{ adminform.form.non_field_errors }} - {% endif %} -
- {% csrf_token %} - {{ formset.non_form_errors.as_ul }} -
- - {% for form in formset.forms %} - {% if forloop.first %} - - - {% for field in form.visible_fields %} - - {% endfor %} - - - {% endif %} - - {% for field in form.visible_fields %} - - {% endfor %} - - {% endfor %} -
- {# Include the hidden fields in the form #} - {% if forloop.first %} - {% for hidden in form.hidden_fields %} - {{ hidden }} - {% endfor %} - {% endif %} - {{ field.errors.as_ul }} - {{ field }} -
-
- {{ formset.management_form }} - {% for hidden in actionform.hidden_fields %} - {{ hidden }} +{% extends "admin/change_form.html" %} {% load actions admin_modify i18n static %} {% block extrahead %}{{ block.super }} + + + +{% endblock extrahead %} {% block breadcrumbs %}{% if not is_popup %} + +{% endif %}{% endblock breadcrumbs %} {% block content %} {% if formset.errors %} +

+ {% if formset.errors|length == 1 %}{% translate "Please correct the error below." %}{% else %}{% translate "Please correct the errors below." %}{%endif %} +

+{{ adminform.form.non_field_errors }} {% endif %} + + {% csrf_token %} {{ formset.non_form_errors.as_ul }} +
+ + {% for form in formset.forms %} {% if forloop.first %} + + + {% for field in form.visible_fields %} + + {% endfor %} + + + {% endif %} + + {% for field in form.visible_fields %} + {% endfor %} - - -{% endblock %} + + {% endfor %} +
+ +
+ {% if forloop.first %} {% for hidden in form.hidden_fields %} {{hidden}} {% endfor %} {% endif %} {{ field.errors.as_ul }} {{ field}} +
+
+ {{ formset.management_form }} {% for hidden in actionform.hidden_fields %} + {{hidden }} {% endfor %} + + +{% endblock content %} diff --git a/src/adminactions/templates/adminactions/charts.html b/src/adminactions/templates/adminactions/charts.html index 773fbb06..f44911ec 100644 --- a/src/adminactions/templates/adminactions/charts.html +++ b/src/adminactions/templates/adminactions/charts.html @@ -1,47 +1,58 @@ -{% extends "admin/change_form.html" %}{% load i18n static admin_modify admin_urls %}{% load url from aa_compat %} -{% block extrahead %} - {{ block.super }} - - - - - - +{% extends "admin/change_form.html" %}{% load admin_modify admin_urls i18n static %}{% load url from aa_compat %} {% block extrahead %} {{ block.super }} + + + + + + - -{% endblock %} - -{% block breadcrumbs %}{% if not is_popup %} - +{% endblock extrahead %} {% block breadcrumbs %}{% if not is_popup %} + +{% endif %} {% endblock breadcrumbs %} {% block content %} +
+
+ -{% csrf_token %}= + + {{ adminform.form }} +
+ + +
+
+{% if graph_type %} +
+
{% endif %} -{% endblock %} - -{% block content %} -
-
-{% csrf_token %}= - - {{ adminform.form }} -
- - -
-
- {% if graph_type %} -
-
- {% endif %} - -{% endblock %} + +{% endblock content %} diff --git a/src/adminactions/templates/adminactions/duplicates.html b/src/adminactions/templates/adminactions/duplicates.html index 3069023b..f9ba20f8 100644 --- a/src/adminactions/templates/adminactions/duplicates.html +++ b/src/adminactions/templates/adminactions/duplicates.html @@ -1,42 +1,52 @@ -{% extends "admin/change_form.html" %}{% load i18n admin_modify actions static %} -{% block extrahead %}{{ block.super }}{{ form.media }}{% endblock %} - -{% block breadcrumbs %}{% if not is_popup %} - -{% endblock %} +{% endblock content %} diff --git a/src/adminactions/templates/adminactions/export_xls.html b/src/adminactions/templates/adminactions/export_xls.html index 13c3afa9..c95f54dc 100644 --- a/src/adminactions/templates/adminactions/export_xls.html +++ b/src/adminactions/templates/adminactions/export_xls.html @@ -1,44 +1,37 @@ -{% extends "admin/change_form.html" %} -{% load i18n admin_modify admin_urls %}{% load url from aa_compat %} -{% block extrahead %}{{ block.super }} - -{% endblock %} - -{% block breadcrumbs %}{% if not is_popup %} - -{% endif %}{% endblock %} - -{% block content %} - {% if adminform.form.subject.errors %} -
    - {% for error in adminform.form.subject.errors %} -
  1. {{ error|escape }}
  2. - {% endfor %} -
- {% endif %} -
-
- {% csrf_token %} - - {{ adminform.form }} -
- -
-
+ #legend { + float: left; + width: 60%; + } + +{% endblock %} {% block breadcrumbs %}{% if not is_popup %} + +{% endif %}{% endblock %} {% block content %} {% if adminform.form.subject.errors %} +
    + {% for error in adminform.form.subject.errors %} +
  1. {{ error|escape }}
  2. + {% endfor %} +
+{% endif %} +
+
+ {% csrf_token %} + + {{ adminform.form }} +
+ +
+
{% endblock %} diff --git a/src/adminactions/templates/adminactions/helpers/import_fixture.html b/src/adminactions/templates/adminactions/helpers/import_fixture.html index 59e2e3d6..30f881db 100644 --- a/src/adminactions/templates/adminactions/helpers/import_fixture.html +++ b/src/adminactions/templates/adminactions/helpers/import_fixture.html @@ -1,22 +1,25 @@ -{% extends "admin_extra_urls/action_page.html" %}{% load i18n static admin_list admin_urls %} -{% block breadcrumbs-items %} - {% trans 'Home' %} - › {{ opts.app_config.verbose_name }} - › {{ opts.verbose_name_plural|capfirst }} - {% if original %} - › {{ original }} - {% endif %} - {% block breadcrumbs-active %}› {{ action|default_if_none:title }}{% endblock breadcrumbs-active %} -{% endblock breadcrumbs-items %} - -{% block action-content %} -
- {% csrf_token %} - +{% extends "admin_extra_urls/action_page.html" %}{% load i18n static admin_list +admin_urls %} {% block breadcrumbs-items %} +{% translate 'Home' %} +› +{{ opts.app_config.verbose_name }} +› +{{ opts.verbose_name_plural|capfirst }} +{% if original %} › +{{ original }} +{% endif %} {% block breadcrumbs-active %}› {{ +action|default_if_none:title }} {% endblock breadcrumbs-active %} {% endblock +breadcrumbs-items %} {% block action-content %} + + {% csrf_token %} +
{{ form }} -
- -
- + + + {% endblock %} diff --git a/src/adminactions/templates/adminactions/mass_update.html b/src/adminactions/templates/adminactions/mass_update.html index a800ccec..363f1099 100644 --- a/src/adminactions/templates/adminactions/mass_update.html +++ b/src/adminactions/templates/adminactions/mass_update.html @@ -1,78 +1,79 @@ -{% extends "admin/change_form.html" %} -{% load i18n admin_modify actions massupdate static %} -{#{% block extrahead %}{{ block.super }}#} -{# {{ media }}#} -{#{% endblock %}#} - -{% block breadcrumbs %}{% if not is_popup %} - -{% endif %}{% endblock %} - -{% block content %} - {% if form.subject.errors %} -
    - {% for error in form.subject.errors %} -
  1. {{ error|escape }}
  2. - {% endfor %} -
- {% endif %} - {{ form.non_field_errors }} -
-
- {% csrf_token %} - - {% for field in adminform.form.configured_fields %} - - - - - {% endfor %} - - - - - - - - - {% if grouped %} - - {% endif %} - - {% for field in adminform.form.model_fields %} - - - - - - {% if grouped %} - - {% endif %} - - - {% endfor %} -
{{ field.label_tag }} - {{ field.errors }} - {{ field }} {{ field.help_text }} -
-{#
#} -
field nameupdatefunctionnew valueexisting values - (sample) -
{% if field.field.required %} - {% endif %} {{ field.label_tag }}{% if field.field.required %}{% endif %} {% checkbox_enabler field %} - {% field_function adminform.model_admin.model field %} {{ field.errors }} - {{ field }}  - {% link_fields_values grouped field.name %} -
- {% for hidden in form.hidden_fields %} - {{ hidden }} - {% endfor %} - -
-
+{% extends "admin/change_form.html" %} {% load i18n admin_modify actions massupdate static %} {% block breadcrumbs %}{% if not is_popup %} + +{% endif %}{% endblock %} {% block content %} {% if form.subject.errors %} +
    + {% for error in form.subject.errors %} +
  1. {{ error|escape }}
  2. + {% endfor %} +
+{% endif %} {{ form.non_field_errors }} +
+
+ {% csrf_token %} + + {% for field in adminform.form.configured_fields %} + + + + + {% endfor %} + + + + + + + + + {% if grouped %} + + {% endif %} + + {% for field in adminform.form.model_fields %} + + + + + + {% if grouped %} + + {% endif %} + + {% endfor %} +
{{ field.label_tag }} + {{ field.errors }} {{ field }} {{ field.help_text }} +
field nameupdatefunctionnew value + existing values + (sample) +
+ {% if field.field.required %} + {% endif %} {{ field.label_tag }}{% if field.field.required %}{% endif %} + {% checkbox_enabler field %} + {% field_function adminform.model_admin.model field %}  + + {{ field.errors }} {{ field }}  + + {% link_fields_values grouped field.name %} +
+ {% for hidden in form.hidden_fields %} {{ hidden }} {% endfor %} + +
+
{% endblock %} diff --git a/src/adminactions/templates/adminactions/merge.html b/src/adminactions/templates/adminactions/merge.html index 42adbdf5..ec637215 100644 --- a/src/adminactions/templates/adminactions/merge.html +++ b/src/adminactions/templates/adminactions/merge.html @@ -1,13 +1,14 @@ {% extends "admin/change_form.html" %} -{% load i18n actions static merge %} +{% load actions i18n merge static %} {% block breadcrumbs %}{% if not is_popup %} -{% endif %}{% endblock %} +{% endif %}{% endblock breadcrumbs %} + {% block content %} {% if not transaction_supported %}
Warning: your database does not support transactios. Merge cannot be validated and/or undone
@@ -31,14 +32,14 @@ - - + - - + + - {% for field in fields %} @@ -47,13 +48,13 @@ @@ -66,7 +67,7 @@ {% endfor %}
{% trans "Field" %}{% trans "Master" %} #{{ master.pk }} ({% trans "This will be preserved" %}) + {% translate "Field" %}{% translate "Master" %} #{{ master.pk }} ({% translate "This will be preserved" %}) {% trans "swap" %}{% trans "Result" %}{% translate "swap" %}{% translate "Result" %} {% trans "Other" %} #{{ other.pk }} ({% trans "This will be removed" %}) - {# {{ adminform.form.other_pk.value }}#} + {% translate "Other" %} #{{ other.pk }} ({% translate "This will be removed" %}) + {# {{ adminform.form.other_pk.value }} #}
{{ formset.0|widget:field.name }} -

{{ master|field_display:field}}

+

{{ master|field_display:field }}

>> {{ adminform.form|widget:field.name }} -

+

{{ adminform.form|errors:field.name }}
- + {% endif %} -{% endblock %} +{% endblock content %} diff --git a/src/adminactions/templates/adminactions/merge_preview.html b/src/adminactions/templates/adminactions/merge_preview.html index 435cd822..719bdd3b 100644 --- a/src/adminactions/templates/adminactions/merge_preview.html +++ b/src/adminactions/templates/adminactions/merge_preview.html @@ -1,41 +1,38 @@ -{% extends "admin/change_form.html" %} -{% load i18n actions static merge %} -{% block breadcrumbs %}{% if not is_popup %} - -{% endif %}{% endblock %} -{% block content %} -
{% csrf_token %} - {% for f in adminform.form.hidden_fields %}{{ f }}{% endfor %} - {% for f in adminform.form.action_fields %}{{ f }}{% endfor %} - - - - - - - - - - - {% for field in fields %} - - - - - {% endfor %} -
{% trans "Key" %}{{ master.pk }}
{% trans "Original" %}{% trans "After Merging" %}
{{ master|verbose_name:field.name }} - {{ original|field_display:field.name }} - - {{ adminform.form|widget:field.name }} - {{ master|field_display:field.name }} - -
- -
+{% extends "admin/change_form.html" %} {% load i18n actions static merge %} {% block breadcrumbs %}{% if not is_popup %} + +{% endif %}{% endblock %} {% block content %} +
+ {% csrf_token %} {% for f in adminform.form.hidden_fields %}{{ f }}{% endfor%} + {% for f in adminform.form.action_fields %}{{ f }}{% endfor %} + + + + + + + + + + + {% for field in fields %} + + + + + {% endfor %} + +
{% translate "Key" %}{{ master.pk }}
{% translate "Original" %}{% translate "After Merging" %}
{{ master|verbose_name:field.name }} + {{ original|field_display:field.name }} + + {{ adminform.form|widget:field.name }} + {{ master|field_display:field.name }} +
+ +
{% endblock %} diff --git a/src/adminactions/templatetags/aa_compat.py b/src/adminactions/templatetags/aa_compat.py index 2a65e697..129d6d98 100644 --- a/src/adminactions/templatetags/aa_compat.py +++ b/src/adminactions/templatetags/aa_compat.py @@ -1,10 +1,11 @@ from django.template import Library +from django.template.base import Parser, Token register = Library() @register.tag -def url(parser, token): +def url(parser: Parser, token: Token) -> str: from django.template.defaulttags import url as _url return _url(parser, token) diff --git a/src/adminactions/templatetags/actions.py b/src/adminactions/templatetags/actions.py index 25f29bb0..0a0312aa 100644 --- a/src/adminactions/templatetags/actions.py +++ b/src/adminactions/templatetags/actions.py @@ -1,12 +1,21 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING, Any + from django.template import Library from adminactions.utils import get_field_value, get_verbose_name +if TYPE_CHECKING: + from django.db.models.base import Model + from django.db.models.fields import Field + from django.db.models.query import QuerySet + register = Library() @register.filter() -def field_display(obj, field): +def field_display(obj: Model, field: Field) -> Any: """ returns the representation (value or ``get_FIELD_display()``) of a field @@ -16,7 +25,7 @@ def field_display(obj, field): @register.filter -def verbose_name(model_or_queryset, field): +def verbose_name(model_or_queryset: Model | QuerySet, field: Field) -> str: """ templatetag wrapper to `adminactions.utils.get_verbose_name`_ """ diff --git a/src/adminactions/templatetags/massupdate.py b/src/adminactions/templatetags/massupdate.py index a38223e3..f4c2aad2 100644 --- a/src/adminactions/templatetags/massupdate.py +++ b/src/adminactions/templatetags/massupdate.py @@ -1,5 +1,8 @@ +from django.db.models.base import Model from django.forms import widgets +from django.forms.fields import Field from django.template import Library +from django.template.context import Context from django.utils.safestring import mark_safe from adminactions.utils import get_field_by_name @@ -8,10 +11,13 @@ @register.simple_tag -def fields_values(d, k): +def fields_values(d: dict[str, list[str]], k: str) -> str: """ - >>> data = {'name1': ['value1.1', 'value1.2'], 'name2': ['value2.1', 'value2.2'], } - >>> print(fields_values(data, 'name1')) + >>> data = { + ... "name1": ["value1.1", "value1.2"], + ... "name2": ["value2.1", "value2.2"], + ... } + >>> print(fields_values(data, "name1")) value1.1,value1.2 """ values = d.get(k, []) @@ -19,7 +25,7 @@ def fields_values(d, k): @register.simple_tag -def link_fields_values(d, field_name): +def link_fields_values(d: dict[str, list[tuple[int, str]]], field_name: str) -> str: """ >>> data = {'name1': [(1, 'value1.1'), (11, 'value1.2')], ... 'name2': [(2, 'value2.1'), (22, 'value2.2')], } @@ -51,7 +57,7 @@ def link_fields_values(d, field_name): @register.simple_tag(takes_context=True) -def checkbox_enabler(context, field): +def checkbox_enabler(context: Context, field: Field) -> str: form = context["adminform"].form name = "chk_id_%s" % field.name checked = "" @@ -62,7 +68,7 @@ def checkbox_enabler(context, field): @register.simple_tag(takes_context=True) -def field_function(context, model, form_field): +def field_function(context: Context, model: Model, form_field: Field) -> widgets.Select: from adminactions.mass_update import OPERATIONS model_field, model, direct, m2m = get_field_by_name(model, form_field.name) diff --git a/src/adminactions/templatetags/merge.py b/src/adminactions/templatetags/merge.py index 6d2a9f36..f41913bd 100644 --- a/src/adminactions/templatetags/merge.py +++ b/src/adminactions/templatetags/merge.py @@ -1,10 +1,15 @@ +from typing import Any + +from django.forms.forms import Form +from django.forms.utils import ErrorList +from django.forms.widgets import Widget from django.template import Library register = Library() @register.filter(name="widget") -def form_widget(form, fieldname): +def form_widget(form: Form, fieldname: str) -> Widget: """ >>> from django.forms import ModelForm, modelform_factory >>> from django.contrib.auth.models import User @@ -16,19 +21,19 @@ def form_widget(form, fieldname): @register.filter(name="errors") -def form_widget_error(form, fieldname): +def form_widget_error(form: Form, fieldname: str) -> list[str]: """ >>> from django.forms import ModelForm, modelform_factory >>> from django.contrib.auth.models import User >>> f = modelform_factory(User, fields=["username"])({}, instance=User()) - >>> form_widget_error(f, "username") == ['This field is required.'] + >>> form_widget_error(f, "username") == ["This field is required."] True """ return form[fieldname].errors @register.filter(name="value") -def form_widget_value(form, fieldname): +def form_widget_value(form: Form, fieldname: str) -> Any: """ >>> from django.forms import ModelForm, modelform_factory >>> from django.contrib.auth.models import User diff --git a/src/adminactions/utils.py b/src/adminactions/utils.py index 1b624a01..d0a6e72e 100644 --- a/src/adminactions/utils.py +++ b/src/adminactions/utils.py @@ -1,21 +1,27 @@ +from __future__ import annotations + from functools import partial +from typing import TYPE_CHECKING, Any, Iterable, Union from django.conf import settings from django.db import models from django.db.models.query import QuerySet from django.utils.encoding import smart_str +if TYPE_CHECKING: + from django.contrib.admin.options import ModelAdmin + from django.db.models.base import Model + from django.db.models.fields import Field + -def get_ignored_fields(model, setting_var_name): +def get_ignored_fields(model: Model, setting_var_name: str) -> Iterable[str]: """ returns list of ignored fields which must not be modified """ - return ( - getattr(settings, setting_var_name, {}).get(model._meta.app_label, {}).get(model._meta.model_name, ()) - ) + return getattr(settings, setting_var_name, {}).get(model._meta.app_label, {}).get(model._meta.model_name, ()) -def clone_instance(instance, fieldnames=None): +def clone_instance(instance: Model, fieldnames: list[str] = None) -> Model: """ returns a copy of the passed instance. @@ -35,19 +41,20 @@ def clone_instance(instance, fieldnames=None): # return instance.__class__.objects.get(pk=instance.pk) -def get_attr(obj, attr, default=None): +def get_attr(obj: Any, attr: str, default: Any | None = None) -> Any: """Recursive get object's attribute. May use dot notation. - >>> class C: pass + >>> class C: + ... pass >>> a = C() >>> a.b = C() >>> a.b.c = 4 - >>> get_attr(a, 'b.c') + >>> get_attr(a, "b.c") 4 - >>> get_attr(a, 'b.c.y', None) + >>> get_attr(a, "b.c.y", None) - >>> get_attr(a, 'b.c.y', 1) + >>> get_attr(a, "b.c.y", 1) 1 """ if "." not in attr: @@ -61,7 +68,7 @@ def get_attr(obj, attr, default=None): return ret -def getattr_or_item(obj, name): +def getattr_or_item(obj: Any, name: str) -> Any: """ works indifferently on dict or objects, retrieving the 'name' attribute or item @@ -70,11 +77,11 @@ def getattr_or_item(obj, name): :param name: attribute or item name :return: >>> from django.contrib.auth.models import Permission - >>> p = Permission(name='perm') - >>> d ={'one': 1, 'two': 2} - >>> getattr_or_item(d, 'one') + >>> p = Permission(name="perm") + >>> d = {"one": 1, "two": 2} + >>> getattr_or_item(d, "one") 1 - >>> print(getattr_or_item(p, 'name')) + >>> print(getattr_or_item(p, "name")) perm """ # this change type from type to dict in python3.9 @@ -92,7 +99,9 @@ def getattr_or_item(obj, name): return ret -def get_field_value(obj, field, usedisplay=True, raw_callable=False, modeladmin=None): +def get_field_value( + obj: Model, field: Field, usedisplay: bool = True, raw_callable: bool = False, modeladmin: ModelAdmin = None +) -> Any: """ returns the field value or field representation if get_FIELD_display exists @@ -102,8 +111,8 @@ def get_field_value(obj, field, usedisplay=True, raw_callable=False, modeladmin= :return: field value >>> from django.contrib.auth.models import Permission - >>> p = Permission(name='perm') - >>> get_field_value(p, 'name') == 'perm' + >>> p = Permission(name="perm") + >>> get_field_value(p, "name") == "perm" True >>> get_field_value(p, None) Traceback (most recent call last): @@ -138,7 +147,7 @@ def get_field_value(obj, field, usedisplay=True, raw_callable=False, modeladmin= return value -def get_field_by_path(model, field_path): +def get_field_by_path(model: Model, field_path: str) -> Field: """ get a Model class or instance and a path to a attribute, returns the field object @@ -149,11 +158,11 @@ def get_field_by_path(model, field_path): >>> from django.contrib.auth.models import Permission - >>> p = Permission(name='perm') - >>> get_field_by_path(Permission, 'content_type').name + >>> p = Permission(name="perm") + >>> get_field_by_path(Permission, "content_type").name 'content_type' - >>> p = Permission(name='perm') - >>> get_field_by_path(p, 'content_type.app_label').name + >>> p = Permission(name="perm") + >>> get_field_by_path(p, "content_type.app_label").name 'app_label' """ parts = field_path.split(".") @@ -170,7 +179,7 @@ def get_field_by_path(model, field_path): return None -def get_verbose_name(model_or_queryset, field): +def get_verbose_name(model_or_queryset: Union[Model, QuerySet], field: Field) -> str: """ returns the value of the ``verbose_name`` of a field @@ -190,17 +199,17 @@ def get_verbose_name(model_or_queryset, field): >>> from django.contrib.auth.models import User, Permission >>> user = User() >>> p = Permission() - >>> get_verbose_name(user, 'username') == 'username' + >>> get_verbose_name(user, "username") == "username" True - >>> get_verbose_name(User, 'username') == 'username' + >>> get_verbose_name(User, "username") == "username" True - >>> get_verbose_name(User.objects.all(), 'username') == 'username' + >>> get_verbose_name(User.objects.all(), "username") == "username" True - >>> get_verbose_name(User.objects, 'username') == 'username' + >>> get_verbose_name(User.objects, "username") == "username" True - >>> get_verbose_name(User.objects, user._meta.fields[0]) == 'ID' + >>> get_verbose_name(User.objects, user._meta.fields[0]) == "ID" True - >>> get_verbose_name(p, 'content_type.model') == 'python model class name' + >>> get_verbose_name(p, "content_type.model") == "python model class name" True """ @@ -228,7 +237,7 @@ def get_verbose_name(model_or_queryset, field): return field.verbose_name -def flatten(iterable): +def flatten(iterable: Iterable) -> list[Any]: """ flatten(sequence) -> list @@ -242,10 +251,10 @@ def flatten(iterable): Examples: >>> from adminactions.utils import flatten - >>> [1, 2, [3,4], (5,6)] + >>> [1, 2, [3, 4], (5, 6)] [1, 2, [3, 4], (5, 6)] - >>> flatten([[[1,2,3], (42,None)], [4,5], [6], 7, (8,9,10)]) + >>> flatten([[[1, 2, 3], (42, None)], [4, 5], [6], 7, (8, 9, 10)]) [1, 2, 3, 42, None, 4, 5, 6, 7, 8, 9, 10]""" result = list() @@ -257,21 +266,21 @@ def flatten(iterable): return list(result) -def get_field_by_name(model, name): +def get_field_by_name(model: Model, name: str) -> (Field, Model, bool, bool): field = model._meta.get_field(name) direct = not field.auto_created or field.concrete return field, field.model, direct, field.many_to_many -def model_has_field(model, field_name): +def model_has_field(model: Model, field_name: str) -> bool: return field_name in [f.name for f in model._meta.get_fields()] -def get_all_related_objects(model): +def get_all_related_objects(model: Model) -> list[str]: return [f for f in model._meta.get_fields() if (f.one_to_many or f.one_to_one) and f.auto_created] -def get_all_field_names(model): +def get_all_field_names(model: Model) -> list[str]: from itertools import chain return list( @@ -285,11 +294,11 @@ def get_all_field_names(model): ) -def curry(func, *a, **kw): +def curry(func: callable, *a: Any, **kw: Any) -> callable: return partial(func, *a, **kw) -def get_common_context(modeladmin, **kwargs): +def get_common_context(modeladmin: ModelAdmin, **kwargs: Any) -> dict[str, Any]: ctx = { "change": True, "is_popup": False, diff --git a/src/adminactions/views.py b/src/adminactions/views.py index 088693c5..44b6d4f8 100644 --- a/src/adminactions/views.py +++ b/src/adminactions/views.py @@ -1,9 +1,10 @@ from datetime import datetime from django.http import HttpResponse +from django.http.request import HttpRequest from django.utils import dateformat -def format_date(request): +def format_date(request: HttpRequest) -> HttpResponse: d = datetime.now() return HttpResponse(dateformat.format(d, request.GET.get("fmt", ""))) diff --git a/src/requirements/develop.pip b/src/requirements/develop.pip deleted file mode 100644 index 5d10e631..00000000 --- a/src/requirements/develop.pip +++ /dev/null @@ -1,7 +0,0 @@ -black -django<4 -pdbpp -virtualenv -wheel -check-manifest -docutils diff --git a/src/requirements/install.pip b/src/requirements/install.pip deleted file mode 100644 index 8441c092..00000000 --- a/src/requirements/install.pip +++ /dev/null @@ -1,3 +0,0 @@ -pytz -xlrd>=0.9.2 -xlwt diff --git a/src/requirements/rtd.pip b/src/requirements/rtd.pip deleted file mode 100644 index 61645a09..00000000 --- a/src/requirements/rtd.pip +++ /dev/null @@ -1,3 +0,0 @@ -django -sphinx -sphinx_rtd_theme diff --git a/src/requirements/testing.pip b/src/requirements/testing.pip deleted file mode 100644 index 58e83dfd..00000000 --- a/src/requirements/testing.pip +++ /dev/null @@ -1,24 +0,0 @@ -check-manifest -celery -django-dynamic-fixture -django-webtest>1.9.6 -django-admin-extra-urls -django-environ -flake8 -flake8-isort -mock>=1.0.1 -modernize -pillow -pytest -pytest-cache -pytest-cov -pytest-django -pytest-echo -redis -readme -selenium>=2.42.0 -setuptools>=15.0 -tox<4 -isort -black - diff --git a/tests/conftest.py b/tests/conftest.py index 79038abb..21e417f4 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import logging import os import shutil @@ -27,7 +29,7 @@ } -def pytest_addoption(parser): +def pytest_addoption(parser) -> None: group = parser.getgroup("selenium", "Selenium Web Browser Automation") group.addoption( "--selenium-enable", @@ -62,7 +64,7 @@ def pytest_addoption(parser): ) -def pytest_configure(config): +def pytest_configure(config) -> None: here = Path(__file__).parent sys.path.insert(0, here) sys.path.insert(0, here.parent / "src") @@ -74,9 +76,8 @@ def pytest_configure(config): config.option.markexpr.find("selenium") < 0 and not config.option.keyword and config.option.keyword.find("selenium") < 0 - ): - if not config.option.selenium_enable: - setattr(config.option, "markexpr", "not selenium") + ) and not config.option.selenium_enable: + config.option.markexpr = "not selenium" os.environ["CELERY_ALWAYS_EAGER"] = "1" os.environ["MEDIA_ROOT"] = "/tmp/media/" settings.MEDIA_ROOT = tempfile.TemporaryDirectory().name @@ -87,7 +88,7 @@ def pytest_configure(config): import logging level = config.option.log_level.upper() - assert level in levelNames.keys() + assert level in levelNames format = "%(levelname)-7s %(name)-30s %(funcName)-20s:%(lineno)3s %(message)s" formatter = logging.Formatter(format) @@ -108,13 +109,13 @@ def pytest_configure(config): @pytest.fixture(autouse=True) -def create_aa_permissions(db): +def create_aa_permissions(db) -> None: from adminactions.perms import create_extra_permissions create_extra_permissions() -@pytest.fixture(scope="function") +@pytest.fixture def app(request): wtm = django_webtest.WebTestMixin() wtm.csrf_checks = False @@ -123,7 +124,7 @@ def app(request): return django_webtest.DjangoTestApp() -@pytest.fixture(scope="function") +@pytest.fixture def users(): from django.contrib.auth.models import User from django_dynamic_fixture import G @@ -131,7 +132,7 @@ def users(): return G(User, n=2, is_staff=False, is_active=False) -@pytest.fixture(scope="function") +@pytest.fixture def demomodels(): from demo.models import DemoModel from django_dynamic_fixture import G @@ -139,7 +140,7 @@ def demomodels(): return G(DemoModel, n=20) -@pytest.fixture(scope="function") +@pytest.fixture def admin(): from django.contrib.auth.models import User from django_dynamic_fixture import G @@ -147,10 +148,9 @@ def admin(): return G(User, is_staff=True, is_active=True) -@pytest.fixture(scope="function") +@pytest.fixture def administrator(): from django.contrib.auth.models import User from utils import ADMIN, PWD - superuser = User._default_manager.create_superuser(username=ADMIN, password=PWD, email="sax@noreply.org") - return superuser + return User._default_manager.create_superuser(username=ADMIN, password=PWD, email="sax@noreply.org") diff --git a/tests/demo/apps.py b/tests/demo/apps.py index 43f0e376..f43130b0 100644 --- a/tests/demo/apps.py +++ b/tests/demo/apps.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from django.apps import AppConfig @@ -5,7 +7,7 @@ class Config(AppConfig): name = "demo" default = True - def ready(self): + def ready(self) -> None: try: from .celery import app # noqa except ImportError: diff --git a/tests/demo/backends.py b/tests/demo/backends.py index bcdaed97..c4fad072 100644 --- a/tests/demo/backends.py +++ b/tests/demo/backends.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from django.contrib.auth.backends import ModelBackend from django.contrib.auth.models import User @@ -7,11 +9,12 @@ def authenticate(self, request, username=None, password=None, **kwargs): if username: user, __ = User.objects.update_or_create( username=username, - defaults=dict( - is_staff=True, - is_active=True, - is_superuser=True, - email=f"{username}@demo.org", - ), + defaults={ + "is_staff": True, + "is_active": True, + "is_superuser": True, + "email": f"{username}@demo.org", + }, ) return user + return None diff --git a/tests/demo/celery.py b/tests/demo/celery.py index b6cd270f..04aa2841 100644 --- a/tests/demo/celery.py +++ b/tests/demo/celery.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import os try: diff --git a/tests/demo/fixtures/adminactions.json b/tests/demo/fixtures/adminactions.json index 5db84a5b..8889025c 100644 --- a/tests/demo/fixtures/adminactions.json +++ b/tests/demo/fixtures/adminactions.json @@ -1,236 +1,235 @@ [ - { - "pk":1, - "model":"auth.user", - "fields":{ - "username":"sax", - "first_name":"", - "last_name":"", - "is_active":true, - "is_superuser":true, - "is_staff":true, - "last_login":"2011-07-07T17:00:00Z", - "groups":[], - "user_permissions":[], - "password":"sha1$eec82$d1cebb645395e1ea755e57e5eeda6d192128ad6b", - "email":"sax@os4d.org", - "date_joined":"2011-07-01T17:00:00Z" - } - }, - { - "pk":2, - "model":"auth.user", - "fields":{ - "username":"user_00", - "first_name":"FirstName 0", - "last_name":"LastName 0", - "is_active":true, - "is_superuser":false, - "is_staff":true, - "last_login": "2020-01-01T17:00:00Z", - "groups":[], - "user_permissions":[], - "password":"sha1$eec82$d1cebb645395e1ea755e57e5eeda6d192128ad6b", - "email":"user_0@test.org", - "date_joined": "2020-01-01T17:00:00Z" - } - }, - { - "pk":3, - "model":"auth.user", - "fields":{ - "username":"user_01", - "first_name":"FirstName 1", - "last_name":"LastName 1", - "is_active":true, - "is_superuser":false, - "is_staff":false, - "last_login":"2011-07-07T17:00:00Z", - "groups":[], - "user_permissions":[], - "password":"sha1$eec82$d1cebb645395e1ea755e57e5eeda6d192128ad6b", - "email":"user_1@test.org", - "date_joined":"2011-07-01T17:00:00Z" - } - }, - { - "pk":4, - "model":"auth.user", - "fields":{ - "username":"user_02", - "first_name":"FirstName 2", - "last_name":"LastName 2", - "is_active":true, - "is_superuser":false, - "is_staff":false, - "last_login":"2011-07-07T17:00:00Z", - "groups":[], - "user_permissions":[], - "password":"", - "email":"user_2@test.org", - "date_joined":"2011-07-01T17:00:00Z" - } - }, - { - "pk":5, - "model":"auth.user", - "fields":{ - "username":"user_03", - "first_name":"FirstName 3", - "last_name":"LastName 3", - "is_active":true, - "is_superuser":false, - "is_staff":false, - "last_login":"2011-07-07T17:00:00Z", - "groups":[], - "user_permissions":[], - "password":"", - "email":"user_3@test.org", - "date_joined":"2011-07-01T17:00:00Z" - } - }, - { - "pk":6, - "model":"auth.user", - "fields":{ - "username":"user_04", - "first_name":"FirstName 4", - "last_name":"LastName 4", - "is_active":true, - "is_superuser":false, - "is_staff":false, - "last_login":"2011-07-07T17:00:00Z", - "groups":[], - "user_permissions":[], - "password":"", - "email":"user_4@test.org", - "date_joined":"2011-07-01T17:00:00Z" - } - }, - { - "pk":7, - "model":"auth.user", - "fields":{ - "username":"user_05", - "first_name":"FirstName 5", - "last_name":"LastName 5", - "is_active":true, - "is_superuser":false, - "is_staff":false, - "last_login":"2011-07-07T17:00:00Z", - "groups":[], - "user_permissions":[], - "password":"", - "email":"user_5@test.org", - "date_joined":"2011-07-01T17:00:00Z" - } - }, - { - "pk":8, - "model":"auth.user", - "fields":{ - "username":"user_06", - "first_name":"FirstName 6", - "last_name":"LastName 6", - "is_active":true, - "is_superuser":false, - "is_staff":false, - "last_login":"2011-07-07T17:00:00Z", - "groups":[], - "user_permissions":[], - "password":"", - "email":"user_6@test.org", - "date_joined":"2011-07-01T17:00:00Z" - } - }, - { - "pk":9, - "model":"auth.user", - "fields":{ - "username":"user_07", - "first_name":"FirstName 7", - "last_name":"LastName 7", - "is_active":true, - "is_superuser":false, - "is_staff":false, - "last_login":"2011-07-07T17:00:00Z", - "groups":[], - "user_permissions":[], - "password":"", - "email":"user_7@test.org", - "date_joined":"2011-07-01T17:00:00Z" - } - }, - { - "pk":10, - "model":"auth.user", - "fields":{ - "username":"user_08", - "first_name":"FirstName 8", - "last_name":"LastName 8", - "is_active":true, - "is_superuser":false, - "is_staff":false, - "last_login":"2011-07-07T17:00:00Z", - "groups":[], - "user_permissions":[], - "password":"", - "email":"user_8@test.org", - "date_joined":"2011-07-01T17:00:00Z" - } - }, - { - "pk":11, - "model":"auth.user", - "fields":{ - "username":"user_09", - "first_name":"FirstName 9", - "last_name":"LastName 9", - "is_active":true, - "is_superuser":false, - "is_staff":false, - "last_login":"2011-07-07T17:00:00Z", - "groups":[], - "user_permissions":[], - "password":"", - "email":"user_9@test.org", - "date_joined":"2011-07-01T17:00:00Z" - } - }, - { - "pk":12, - "model":"auth.user", - "fields":{ - "username":"user_10", - "first_name":"FirstName 10", - "last_name":"LastName 10", - "is_active":true, - "is_superuser":false, - "is_staff":false, - "last_login":"2011-07-07T17:00:00Z", - "groups":[], - "user_permissions":[], - "password":"", - "email":"user_10@test.org", - "date_joined":"2011-07-01T17:00:00Z" - } - }, - - { - "pk":2, - "model":"auth.group", - "fields":{ - "name":"admin", - "permissions":[] - } - }, - { - "pk":1, - "model":"auth.group", - "fields":{ - "name":"guest", - "permissions":[] - } + { + "pk": 1, + "model": "auth.user", + "fields": { + "username": "sax", + "first_name": "", + "last_name": "", + "is_active": true, + "is_superuser": true, + "is_staff": true, + "last_login": "2011-07-07T17:00:00Z", + "groups": [], + "user_permissions": [], + "password": "sha1$eec82$d1cebb645395e1ea755e57e5eeda6d192128ad6b", + "email": "sax@os4d.org", + "date_joined": "2011-07-01T17:00:00Z" + } + }, + { + "pk": 2, + "model": "auth.user", + "fields": { + "username": "user_00", + "first_name": "FirstName 0", + "last_name": "LastName 0", + "is_active": true, + "is_superuser": false, + "is_staff": true, + "last_login": "2020-01-01T17:00:00Z", + "groups": [], + "user_permissions": [], + "password": "sha1$eec82$d1cebb645395e1ea755e57e5eeda6d192128ad6b", + "email": "user_0@test.org", + "date_joined": "2020-01-01T17:00:00Z" + } + }, + { + "pk": 3, + "model": "auth.user", + "fields": { + "username": "user_01", + "first_name": "FirstName 1", + "last_name": "LastName 1", + "is_active": true, + "is_superuser": false, + "is_staff": false, + "last_login": "2011-07-07T17:00:00Z", + "groups": [], + "user_permissions": [], + "password": "sha1$eec82$d1cebb645395e1ea755e57e5eeda6d192128ad6b", + "email": "user_1@test.org", + "date_joined": "2011-07-01T17:00:00Z" + } + }, + { + "pk": 4, + "model": "auth.user", + "fields": { + "username": "user_02", + "first_name": "FirstName 2", + "last_name": "LastName 2", + "is_active": true, + "is_superuser": false, + "is_staff": false, + "last_login": "2011-07-07T17:00:00Z", + "groups": [], + "user_permissions": [], + "password": "", + "email": "user_2@test.org", + "date_joined": "2011-07-01T17:00:00Z" + } + }, + { + "pk": 5, + "model": "auth.user", + "fields": { + "username": "user_03", + "first_name": "FirstName 3", + "last_name": "LastName 3", + "is_active": true, + "is_superuser": false, + "is_staff": false, + "last_login": "2011-07-07T17:00:00Z", + "groups": [], + "user_permissions": [], + "password": "", + "email": "user_3@test.org", + "date_joined": "2011-07-01T17:00:00Z" + } + }, + { + "pk": 6, + "model": "auth.user", + "fields": { + "username": "user_04", + "first_name": "FirstName 4", + "last_name": "LastName 4", + "is_active": true, + "is_superuser": false, + "is_staff": false, + "last_login": "2011-07-07T17:00:00Z", + "groups": [], + "user_permissions": [], + "password": "", + "email": "user_4@test.org", + "date_joined": "2011-07-01T17:00:00Z" + } + }, + { + "pk": 7, + "model": "auth.user", + "fields": { + "username": "user_05", + "first_name": "FirstName 5", + "last_name": "LastName 5", + "is_active": true, + "is_superuser": false, + "is_staff": false, + "last_login": "2011-07-07T17:00:00Z", + "groups": [], + "user_permissions": [], + "password": "", + "email": "user_5@test.org", + "date_joined": "2011-07-01T17:00:00Z" } + }, + { + "pk": 8, + "model": "auth.user", + "fields": { + "username": "user_06", + "first_name": "FirstName 6", + "last_name": "LastName 6", + "is_active": true, + "is_superuser": false, + "is_staff": false, + "last_login": "2011-07-07T17:00:00Z", + "groups": [], + "user_permissions": [], + "password": "", + "email": "user_6@test.org", + "date_joined": "2011-07-01T17:00:00Z" + } + }, + { + "pk": 9, + "model": "auth.user", + "fields": { + "username": "user_07", + "first_name": "FirstName 7", + "last_name": "LastName 7", + "is_active": true, + "is_superuser": false, + "is_staff": false, + "last_login": "2011-07-07T17:00:00Z", + "groups": [], + "user_permissions": [], + "password": "", + "email": "user_7@test.org", + "date_joined": "2011-07-01T17:00:00Z" + } + }, + { + "pk": 10, + "model": "auth.user", + "fields": { + "username": "user_08", + "first_name": "FirstName 8", + "last_name": "LastName 8", + "is_active": true, + "is_superuser": false, + "is_staff": false, + "last_login": "2011-07-07T17:00:00Z", + "groups": [], + "user_permissions": [], + "password": "", + "email": "user_8@test.org", + "date_joined": "2011-07-01T17:00:00Z" + } + }, + { + "pk": 11, + "model": "auth.user", + "fields": { + "username": "user_09", + "first_name": "FirstName 9", + "last_name": "LastName 9", + "is_active": true, + "is_superuser": false, + "is_staff": false, + "last_login": "2011-07-07T17:00:00Z", + "groups": [], + "user_permissions": [], + "password": "", + "email": "user_9@test.org", + "date_joined": "2011-07-01T17:00:00Z" + } + }, + { + "pk": 12, + "model": "auth.user", + "fields": { + "username": "user_10", + "first_name": "FirstName 10", + "last_name": "LastName 10", + "is_active": true, + "is_superuser": false, + "is_staff": false, + "last_login": "2011-07-07T17:00:00Z", + "groups": [], + "user_permissions": [], + "password": "", + "email": "user_10@test.org", + "date_joined": "2011-07-01T17:00:00Z" + } + }, + { + "pk": 2, + "model": "auth.group", + "fields": { + "name": "admin", + "permissions": [] + } + }, + { + "pk": 1, + "model": "auth.group", + "fields": { + "name": "guest", + "permissions": [] + } + } ] diff --git a/tests/demo/fixtures/demoproject.json b/tests/demo/fixtures/demoproject.json index 0a616eae..747291d9 100644 --- a/tests/demo/fixtures/demoproject.json +++ b/tests/demo/fixtures/demoproject.json @@ -1,80 +1,80 @@ [ - { - "pk": 1, - "model": "demo.demomodel", - "fields": { - "nullable": "aaaa", - "float": 10.1, - "generic_ip": "192.168.10.1", - "url": "https://github.com/saxix/django-adminactions", - "decimal": "10.1", - "time": "09:18:35", - "blank": "", - "datetime": "2012-10-06T02:18:33Z", - "char": "bbb", - "not_editable": null, - "bigint": 1111, - "text": "sddd", - "logic": false, - "date": "2012-10-06", - "integer": 90000, - "unique": "unique 1", - "email": "s.apostolico@gmail.com", - "choices": 2, - "image": "second.png", - "subclassed_image": false - } - }, - { - "pk": 2, - "model": "demo.demomodel", - "fields": { - "nullable": "bbbb", - "float": 10.1, - "generic_ip": "192.168.10.2", - "url": "https://github.com/saxix/django-adminactions", - "decimal": "22.2", - "time": "19:00:35", - "blank": "", - "datetime": "2013-01-01T02:18:33Z", - "char": "ccccc", - "not_editable": null, - "bigint": 333333333, - "text": "lorem ipsum", - "logic": false, - "date": "2013-01-29", - "integer": 888888, - "unique": "unique 2", - "email": "s.apostolico@gmail.com", - "choices": 2, - "image": "first.png", - "subclassed_image": "subclassed_first.png" - } - }, - { - "pk": 3, - "model": "demo.demomodel", - "fields": { - "nullable": "dddd", - "float": 10.1, - "generic_ip": "192.168.10.2", - "url": "https://github.com/saxix/django-adminactions", - "decimal": "22.2", - "time": "19:00:35", - "blank": "", - "datetime": "2013-01-01T02:18:33Z", - "char": "Pizzä ïs Gööd", - "not_editable": null, - "bigint": 333333333, - "text": "lorem ipsum", - "logic": false, - "date": "2013-01-29", - "integer": 888888, - "unique": "unique 3", - "email": "s.apostolico@gmail.com", - "choices": 2, - "image": null, - "subclassed_image": "subclassed_second.png" - } + { + "pk": 1, + "model": "demo.demomodel", + "fields": { + "nullable": "aaaa", + "float": 10.1, + "generic_ip": "192.168.10.1", + "url": "https://github.com/saxix/django-adminactions", + "decimal": "10.1", + "time": "09:18:35", + "blank": "", + "datetime": "2012-10-06T02:18:33Z", + "char": "bbb", + "not_editable": null, + "bigint": 1111, + "text": "sddd", + "logic": false, + "date": "2012-10-06", + "integer": 90000, + "unique": "unique 1", + "email": "s.apostolico@gmail.com", + "choices": 2, + "image": "second.png", + "subclassed_image": false } + }, + { + "pk": 2, + "model": "demo.demomodel", + "fields": { + "nullable": "bbbb", + "float": 10.1, + "generic_ip": "192.168.10.2", + "url": "https://github.com/saxix/django-adminactions", + "decimal": "22.2", + "time": "19:00:35", + "blank": "", + "datetime": "2013-01-01T02:18:33Z", + "char": "ccccc", + "not_editable": null, + "bigint": 333333333, + "text": "lorem ipsum", + "logic": false, + "date": "2013-01-29", + "integer": 888888, + "unique": "unique 2", + "email": "s.apostolico@gmail.com", + "choices": 2, + "image": "first.png", + "subclassed_image": "subclassed_first.png" + } + }, + { + "pk": 3, + "model": "demo.demomodel", + "fields": { + "nullable": "dddd", + "float": 10.1, + "generic_ip": "192.168.10.2", + "url": "https://github.com/saxix/django-adminactions", + "decimal": "22.2", + "time": "19:00:35", + "blank": "", + "datetime": "2013-01-01T02:18:33Z", + "char": "Pizzä ïs Gööd", + "not_editable": null, + "bigint": 333333333, + "text": "lorem ipsum", + "logic": false, + "date": "2013-01-29", + "integer": 888888, + "unique": "unique 3", + "email": "s.apostolico@gmail.com", + "choices": 2, + "image": null, + "subclassed_image": "subclassed_second.png" + } + } ] diff --git a/tests/demo/migrations/0001_initial.py b/tests/demo/migrations/0001_initial.py index 615c1f5a..b95e1131 100644 --- a/tests/demo/migrations/0001_initial.py +++ b/tests/demo/migrations/0001_initial.py @@ -1,12 +1,13 @@ -# Generated by Django 2.0.1 on 2018-01-29 00:00 +# Generated by Django 5.1.6 on 2025-02-07 08:31 import uuid -import demo.models import django.db.models.deletion from django.conf import settings from django.db import migrations, models +import demo.models + class Migration(migrations.Migration): initial = True @@ -21,7 +22,7 @@ class Migration(migrations.Migration): fields=[ ( "id", - models.AutoField( + models.BigAutoField( auto_created=True, primary_key=True, serialize=False, @@ -71,7 +72,7 @@ class Migration(migrations.Migration): fields=[ ( "id", - models.AutoField( + models.BigAutoField( auto_created=True, primary_key=True, serialize=False, @@ -83,7 +84,7 @@ class Migration(migrations.Migration): models.OneToOneField( on_delete=django.db.models.deletion.CASCADE, related_name="onetoone", - to="demo.DemoModel", + to="demo.demomodel", ), ), ], @@ -93,7 +94,7 @@ class Migration(migrations.Migration): fields=[ ( "id", - models.AutoField( + models.BigAutoField( auto_created=True, primary_key=True, serialize=False, @@ -103,9 +104,9 @@ class Migration(migrations.Migration): ( "demo", models.ForeignKey( - on_delete=models.deletion.CASCADE, - to="demo.DemoModel", + on_delete=django.db.models.deletion.CASCADE, related_name="related", + to="demo.demomodel", to_field="uuid", ), ), @@ -116,7 +117,7 @@ class Migration(migrations.Migration): fields=[ ( "id", - models.AutoField( + models.BigAutoField( auto_created=True, primary_key=True, serialize=False, diff --git a/tests/demo/models.py b/tests/demo/models.py index c0a20372..9a888603 100644 --- a/tests/demo/models.py +++ b/tests/demo/models.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import uuid from admin_extra_urls.api import button @@ -90,7 +92,7 @@ def import_fixture(self, request): return _import_fixture(self, request) - def get_custom_field(self, instance): + def get_custom_field(self, instance) -> str: return f"model-attribute-{instance.pk}" diff --git a/tests/demo/settings.py b/tests/demo/settings.py index 87c22d62..9b4fed3c 100644 --- a/tests/demo/settings.py +++ b/tests/demo/settings.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import os from environ import Env @@ -15,78 +17,81 @@ "django.core.files.uploadhandler.MemoryFileUploadHandler", "django.core.files.uploadhandler.TemporaryFileUploadHandler", ] - -db = os.environ.get("DBENGINE", None) -if db == "pg": - DATABASES = { - "default": { - "ENGINE": "django.db.backends.postgresql_psycopg2", - "NAME": "adminactions", - "HOST": os.environ.get("PG_HOST", "127.0.0.1"), - "PORT": os.environ.get("PG_PORT", ""), - "USER": os.environ.get("PG_USER", "postgres"), - "PASSWORD": os.environ.get("PG_PASSWORD", ""), - } - } -elif db == "mysql": - DATABASES = { - "default": { - "ENGINE": "django.db.backends.mysql", - "NAME": "adminactions", - "HOST": os.environ.get("MYSQL_HOST", "127.0.0.1"), - "PORT": os.environ.get("MYSQL_PORT", ""), - "USER": os.environ.get("MYSQL_USER", "root"), - "PASSWORD": os.environ.get("MYSQL_PASSWORD", ""), - "CHARSET": "utf8", - "COLLATION": "utf8_general_ci", - "TEST": { - "CHARSET": "utf8", - "COLLATION": "utf8_general_ci", - }, - "TEST_CHARSET": "utf8", - "TEST_COLLATION": "utf8_general_ci", - } - } -elif db == "myisam": - DATABASES = { - "default": { - "ENGINE": "django.db.backends.mysql", - "NAME": "adminactions", - "HOST": os.environ.get("MYSQL_HOST", "127.0.0.1"), - "PORT": os.environ.get("MYSQL_PORT", ""), - "USER": os.environ.get("MYSQL_USER", "root"), - "PASSWORD": os.environ.get("MYSQL_PASSWORD", ""), - "CHARSET": "utf8", - "OPTIONS": {"init_command": "SET storage_engine=MyISAM"}, - "COLLATION": "utf8_general_ci", - "TEST": { - "CHARSET": "utf8", - "COLLATION": "utf8_general_ci", - }, - "TEST_CHARSET": "utf8", - "TEST_COLLATION": "utf8_general_ci", - } - } -else: - DATABASES = { - "default": { - "ENGINE": "django.db.backends.sqlite3", - "NAME": "adminactions.sqlite", - "TEST": { - "NAME": ":memory:", - }, - "TEST_NAME": ":memory:", - "HOST": "", - "PORT": "", - "ATOMIC_REQUESTS": True, - } - } +env = Env() +DATABASES = {"default": env.db("DATABASE_URL")} + +# +# db = os.environ.get("DBENGINE", None) +# if db == "pg": +# DATABASES = { +# "default": { +# "ENGINE": "django.db.backends.postgresql_psycopg2", +# "NAME": "adminactions", +# "HOST": os.environ.get("PG_HOST", "127.0.0.1"), +# "PORT": os.environ.get("PG_PORT", ""), +# "USER": os.environ.get("PG_USER", "postgres"), +# "PASSWORD": os.environ.get("PG_PASSWORD", ""), +# } +# } +# elif db == "mysql": +# DATABASES = { +# "default": { +# "ENGINE": "django.db.backends.mysql", +# "NAME": "adminactions", +# "HOST": os.environ.get("MYSQL_HOST", "127.0.0.1"), +# "PORT": os.environ.get("MYSQL_PORT", ""), +# "USER": os.environ.get("MYSQL_USER", "root"), +# "PASSWORD": os.environ.get("MYSQL_PASSWORD", ""), +# "CHARSET": "utf8", +# "COLLATION": "utf8_general_ci", +# "TEST": { +# "CHARSET": "utf8", +# "COLLATION": "utf8_general_ci", +# }, +# "TEST_CHARSET": "utf8", +# "TEST_COLLATION": "utf8_general_ci", +# } +# } +# elif db == "myisam": +# DATABASES = { +# "default": { +# "ENGINE": "django.db.backends.mysql", +# "NAME": "adminactions", +# "HOST": os.environ.get("MYSQL_HOST", "127.0.0.1"), +# "PORT": os.environ.get("MYSQL_PORT", ""), +# "USER": os.environ.get("MYSQL_USER", "root"), +# "PASSWORD": os.environ.get("MYSQL_PASSWORD", ""), +# "CHARSET": "utf8", +# "OPTIONS": {"init_command": "SET storage_engine=MyISAM"}, +# "COLLATION": "utf8_general_ci", +# "TEST": { +# "CHARSET": "utf8", +# "COLLATION": "utf8_general_ci", +# }, +# "TEST_CHARSET": "utf8", +# "TEST_COLLATION": "utf8_general_ci", +# } +# } +# else: +# DATABASES = { +# "default": { +# "ENGINE": "django.db.backends.sqlite3", +# "NAME": "adminactions.sqlite", +# "TEST": { +# "NAME": ":memory:", +# }, +# "TEST_NAME": ":memory:", +# "HOST": "", +# "PORT": "", +# "ATOMIC_REQUESTS": True, +# } +# } TIME_ZONE = "Asia/Bangkok" LANGUAGE_CODE = "en-us" SITE_ID = 1 USE_I18N = True -USE_L10N = True +# USE_L10N = True USE_TZ = True MEDIA_ROOT = os.environ.get("MEDIA_ROOT", os.path.join(DEMO_DIR, "media")) MEDIA_URL = "" @@ -193,3 +198,4 @@ # CELERY_RESULT_SERIALIZER = "json" # CELERY_TIMEZONE = TIME_ZONE # CELERY_BEAT_SCHEDULER = "django_celery_beat.schedulers:DatabaseScheduler" +DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" diff --git a/tests/demo/storage.py b/tests/demo/storage.py index 238cf08a..7e4d62ef 100644 --- a/tests/demo/storage.py +++ b/tests/demo/storage.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import json from django.conf import settings @@ -60,7 +62,7 @@ class PlainCookieStorage(BaseStorage): not_finished = "__messagesnotfinished__" key_salt = "django.contrib.messages" - def __init__(self, *args, **kwargs): + def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) self.signer = signing.get_cookie_signer(salt=self.key_salt) @@ -79,7 +81,7 @@ def _get(self, *args, **kwargs): messages.pop() return messages, all_retrieved - def _update_cookie(self, encoded_data, response): + def _update_cookie(self, encoded_data, response) -> None: """ Either set the cookie with the encoded data if there is any data to store, or delete the cookie. @@ -119,7 +121,7 @@ def stored_length(val): unstored_messages.append(messages.pop(0)) else: unstored_messages.insert(0, messages.pop()) - encoded_data = self._encode(messages + [self.not_finished], encode_empty=unstored_messages) + encoded_data = self._encode([*messages, self.not_finished], encode_empty=unstored_messages) self._update_cookie(encoded_data, response) return unstored_messages @@ -147,6 +149,7 @@ def _encode(self, messages, encode_empty=False): encoder = MessageEncoder(separators=(",", ":")) value = encoder.encode(messages) return self.signer.sign(value) + return None def _decode(self, data): """ diff --git a/tests/demo/urls.py b/tests/demo/urls.py index ad76f244..46c2ce45 100644 --- a/tests/demo/urls.py +++ b/tests/demo/urls.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from django.contrib import admin from django.urls import include, re_path @@ -8,7 +10,6 @@ admin.site.enable_nav_sidebar = False urlpatterns = ( - re_path(r"admin/", admin.site.urls), re_path(r"as/", include("adminactions.urls")), re_path(r"", admin.site.urls), ) diff --git a/tests/selenium_tests/conftest.py b/tests/selenium_tests/conftest.py index cfed99bb..39e7e681 100644 --- a/tests/selenium_tests/conftest.py +++ b/tests/selenium_tests/conftest.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import os import types @@ -33,9 +35,9 @@ def go(self, url): self._last_url = url return self.get(self.live_server.url + url) - def dump(self, filename=None): + def dump(self, filename=None) -> None: dest = filename or self._last_url.replace("/", "_").replace("#", "~") - self.get_screenshot_as_file("./{}.jpg".format(dest)) + self.get_screenshot_as_file(f"./{dest}.jpg") b = driver b.live_server = live_server @@ -64,7 +66,7 @@ def login(browser): return browser -@pytest.fixture(scope="function") +@pytest.fixture def admin_site(browser, administrator): from demo.models import DemoModel, UserDetail diff --git a/tests/selenium_tests/test_export_csv.py b/tests/selenium_tests/test_export_csv.py index 79374f9f..9f2d51a2 100644 --- a/tests/selenium_tests/test_export_csv.py +++ b/tests/selenium_tests/test_export_csv.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import datetime from time import sleep @@ -10,7 +12,7 @@ @pytest.fixture -def now(monkeypatch): +def now(monkeypatch) -> None: class FixedDateTime: @classmethod def now(cls): @@ -19,8 +21,8 @@ def now(cls): monkeypatch.setattr("adminactions.views.datetime", FixedDateTime) -def test_export_as_csv(admin_site): - browser, administrator = admin_site +def test_export_as_csv(admin_site) -> None: + browser, _administrator = admin_site browser.find_element_by_link_text("Demo models").click() browser.find_element_by_id("action-toggle").click() Select(browser.find_element_by_name("action")).select_by_visible_text("Export as CSV") @@ -39,19 +41,19 @@ def export_csv_page(admin_site): return browser, administrator -def _test(browser, target, format, sample_num, expected_value): +def _test(browser, target, format, sample_num, expected_value) -> None: fmt = browser.find_element_by_id(target) fmt.clear() fmt.send_keys(format) sleep(1) sample = browser.find_elements_by_css_selector("span.sample")[sample_num] # expected_value = dateformat.format(datetime.datetime.now(), format) - assert sample.text == expected_value, "Failed Ajax call on %s" % target + assert sample.text == expected_value, f"Failed Ajax call on {target}" # @pytest.mark.skipif('django.VERSION[:2]==(1,8)') -def test_datetime_format_ajax(export_csv_page, now): - browser, administrator = export_csv_page +def test_datetime_format_ajax(export_csv_page, now) -> None: + browser, _administrator = export_csv_page _test(browser, "id_datetime_format", "l, d F Y", 0, "Friday, 25 December 2020") _test(browser, "id_date_format", "d F Y", 1, "25 December 2020") _test(browser, "id_time_format", "H:i", 2, "17:05") diff --git a/tests/selenium_tests/test_export_xls.py b/tests/selenium_tests/test_export_xls.py index 13348606..3c7f06fb 100644 --- a/tests/selenium_tests/test_export_xls.py +++ b/tests/selenium_tests/test_export_xls.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pytest from selenium.webdriver.support.select import Select diff --git a/tests/selenium_tests/test_mass_update.py b/tests/selenium_tests/test_mass_update.py index 16b81307..c89ccce7 100644 --- a/tests/selenium_tests/test_mass_update.py +++ b/tests/selenium_tests/test_mass_update.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pytest from django.contrib.auth.models import User from selenium.webdriver.support.select import Select @@ -5,19 +7,17 @@ pytestmark = pytest.mark.selenium -def test_mass_update_1(admin_site): +def test_mass_update_1(admin_site) -> None: """ Check Boolean Field. Common values are not filled in boolean fields ( there is no reason to do that ). """ assert User.objects.filter(is_active=True).count() > 1 # sanity check sax = User.objects.get(username="sax") - browser, administrator = admin_site + browser, _administrator = admin_site browser.find_element_by_link_text("Users").click() browser.find_element_by_id("action-toggle").click() - browser.find_element_by_xpath( - "//input[@name='_selected_action' and @value='%s']" % sax.pk - ).click() # unselect sax + browser.find_element_by_xpath(f"//input[@name='_selected_action' and @value='{sax.pk}']").click() # unselect sax Select(browser.find_element_by_name("action")).select_by_visible_text("Mass update") browser.find_element_by_name("index").click() # execute diff --git a/tests/test_api.py b/tests/test_api.py index 32860bdb..0a851a6d 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import csv import io import unittest @@ -13,32 +15,26 @@ class TestExportQuerySetAsCsv(TestCase): - def test_default_params(self): + def test_default_params(self) -> None: with self.assertNumQueries(1): qs = Permission.objects.select_related().filter(codename="add_user") ret = export_as_csv(queryset=qs) - self.assertIsInstance(ret, HttpResponse) + assert isinstance(ret, HttpResponse) if django.VERSION[0] == 2: - self.assertEqual( - ret.content.decode("utf8"), - '"%s";"Can add user";"user";"add_user"\r\n' % qs[0].pk, - ) + assert ret.content.decode("utf8") == f'"{qs[0].pk}";"Can add user";"user";"add_user"\r\n' elif django.VERSION[0] == 3: - self.assertEqual( - ret.content.decode("utf8"), - '"%s";"Can add user";"auth | user";"add_user"\r\n' % qs[0].pk, - ) + assert ret.content.decode("utf8") == f'"{qs[0].pk}";"Can add user";"auth | user";"add_user"\r\n' - def test_header_is_true(self): + def test_header_is_true(self) -> None: mem = io.StringIO() with self.assertNumQueries(1): qs = Permission.objects.select_related().filter(codename="add_user") export_as_csv(queryset=qs, header=True, out=mem) mem.seek(0) csv_reader = csv.reader(mem) - self.assertEqual(next(csv_reader), ['id;"name";"content_type";"codename"']) + assert next(csv_reader) == ['id;"name";"content_type";"codename"'] - def test_queryset_values(self): + def test_queryset_values(self) -> None: fields = ["codename", "content_type__app_label"] header = ["Name", "Application"] mem = io.StringIO() @@ -47,9 +43,9 @@ def test_queryset_values(self): export_as_csv(queryset=qs, fields=fields, header=header, out=mem) mem.seek(0) csv_dump = mem.read() - self.assertEqual(csv_dump, '"Name";"Application"\r\n"add_user";"auth"\r\n') + assert csv_dump == '"Name";"Application"\r\n"add_user";"auth"\r\n' - def test_callable_method(self): + def test_callable_method(self) -> None: fields = ["codename", "natural_key"] mem = io.StringIO() with self.assertNumQueries(2): @@ -57,9 +53,9 @@ def test_callable_method(self): export_as_csv(queryset=qs, fields=fields, out=mem) mem.seek(0) csv_dump = mem.read() - self.assertEqual(csv_dump, "\"add_user\";\"('add_user', 'auth', 'user')\"\r\n") + assert csv_dump == "\"add_user\";\"('add_user', 'auth', 'user')\"\r\n" - def test_deep_attr(self): + def test_deep_attr(self) -> None: fields = ["codename", "content_type.app_label"] mem = io.StringIO() with self.assertNumQueries(1): @@ -67,11 +63,11 @@ def test_deep_attr(self): export_as_csv(queryset=qs, fields=fields, out=mem) mem.seek(0) csv_dump = mem.read() - self.assertEqual(csv_dump, '"add_user";"auth"\r\n') + assert csv_dump == '"add_user";"auth"\r\n' class TestExportAsCsv(unittest.TestCase): - def test_export_as_csv(self): + def test_export_as_csv(self) -> None: fields = ["field1", "field2"] header = ["Field 1", "Field 2"] Row = namedtuple("Row", fields) @@ -80,9 +76,9 @@ def test_export_as_csv(self): export_as_csv(queryset=rows, fields=fields, header=header, out=mem) mem.seek(0) csv_dump = mem.read() - self.assertEqual(csv_dump, '"Field 1";"Field 2"\r\n"1";"4"\r\n"2";"5"\r\n"3";"ӼӳӬԖԊ"\r\n') + assert csv_dump == '"Field 1";"Field 2"\r\n"1";"4"\r\n"2";"5"\r\n"3";"ӼӳӬԖԊ"\r\n' - def test_dialect(self): + def test_dialect(self) -> None: fields = ["field1", "field2"] header = ["Field 1", "Field 2"] Row = namedtuple("Row", fields) @@ -97,17 +93,17 @@ def test_dialect(self): ) mem.seek(0) csv_dump = mem.read() - self.assertEqual(csv_dump, "Field 1,Field 2\r\n1,4\r\n2,5\r\n3,ӼӳӬԖԊ\r\n") + assert csv_dump == "Field 1,Field 2\r\n1,4\r\n2,5\r\n3,ӼӳӬԖԊ\r\n" class TestExportAsExcel(TestCase): - def test_default_params(self): + def test_default_params(self) -> None: with self.assertNumQueries(1): qs = Permission.objects.select_related().filter(codename="add_user") ret = export_as_xls(queryset=qs) - self.assertIsInstance(ret, HttpResponse) + assert isinstance(ret, HttpResponse) - def test_header_is_true(self): + def test_header_is_true(self) -> None: mem = io.BytesIO() with self.assertNumQueries(1): qs = Permission.objects.select_related().filter(codename="add_user") @@ -115,9 +111,9 @@ def test_header_is_true(self): mem.seek(0) xls_workbook = xlrd.open_workbook(file_contents=mem.read()) xls_sheet = xls_workbook.sheet_by_index(0) - self.assertEqual(xls_sheet.row_values(0)[:], ["#", "ID", "name", "content type", "codename"]) + assert xls_sheet.row_values(0)[:] == ["#", "ID", "name", "content type", "codename"] - def test_export_as_xls(self): + def test_export_as_xls(self) -> None: fields = ["field1", "field2"] header = ["Field 1", "Field 2"] Row = namedtuple("Row", fields) @@ -128,14 +124,14 @@ def test_export_as_xls(self): xls_workbook = xlrd.open_workbook(file_contents=mem.read()) xls_sheet = xls_workbook.sheet_by_index(0) - self.assertEqual(xls_sheet.row_values(0)[:], ["#", "Field 1", "Field 2"]) - self.assertEqual(xls_sheet.row_values(1)[:], [1.0, 111.0, 222.0]) - self.assertEqual(xls_sheet.row_values(2)[:], [2.0, 333.0, 444.0]) - self.assertEqual(xls_sheet.row_values(3)[:], [3.0, 555.0, "ӼӳӬԖԊ"]) + assert xls_sheet.row_values(0)[:] == ["#", "Field 1", "Field 2"] + assert xls_sheet.row_values(1)[:] == [1.0, 111.0, 222.0] + assert xls_sheet.row_values(2)[:] == [2.0, 333.0, 444.0] + assert xls_sheet.row_values(3)[:] == [3.0, 555.0, "ӼӳӬԖԊ"] class TestExportQuerySetAsExcel(TestCase): - def test_queryset_values(self): + def test_queryset_values(self) -> None: fields = ["codename", "content_type__app_label"] header = ["Name", "Application"] qs = Permission.objects.filter(codename="add_user").values("codename", "content_type__app_label") @@ -144,10 +140,10 @@ def test_queryset_values(self): mem.seek(0) w = xlrd.open_workbook(file_contents=mem.read()) sheet = w.sheet_by_index(0) - self.assertEqual(sheet.cell_value(1, 1), "add_user") - self.assertEqual(sheet.cell_value(1, 2), "auth") + assert sheet.cell_value(1, 1) == "add_user" + assert sheet.cell_value(1, 2) == "auth" - def test_callable_method(self): + def test_callable_method(self) -> None: fields = ["codename", "natural_key"] qs = Permission.objects.filter(codename="add_user") mem = io.BytesIO() @@ -156,5 +152,5 @@ def test_callable_method(self): content = mem.read() w = xlrd.open_workbook(file_contents=content) sheet = w.sheet_by_index(0) - self.assertEqual(sheet.cell_value(1, 1), "add_user") - self.assertEqual(sheet.cell_value(1, 2), "add_userauthuser") + assert sheet.cell_value(1, 1) == "add_user" + assert sheet.cell_value(1, 2) == "add_userauthuser" diff --git a/tests/test_bulk_update.py b/tests/test_bulk_update.py index 2a71c1f4..dde3e238 100644 --- a/tests/test_bulk_update.py +++ b/tests/test_bulk_update.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import csv from pathlib import Path @@ -30,7 +32,7 @@ class BulkUpdate(SelectRowsMixin, CheckSignalsMixin, WebTestMixin): action_name = "bulk_update" sender_model = DemoModel - def setUp(self): + def setUp(self) -> None: super().setUp() self._url = reverse("admin:demo_demomodel_changelist") self.user = G(User, username="user", is_staff=True, is_active=True) @@ -84,9 +86,7 @@ def _run_action_related_model(self, steps=2, **kwargs): self._select_rows(form, selected_rows) res = form.submit() if steps >= 2: - res.forms["bulk-update"]["_file"] = Upload( - str(Path(__file__).parent / "related_model_bulk_update.csv") - ) + res.forms["bulk-update"]["_file"] = Upload(str(Path(__file__).parent / "related_model_bulk_update.csv")) res.forms["bulk-update"]["fld-id"] = "id" res.forms["bulk-update"]["fld-index_field"] = ["id"] res.forms["bulk-update"]["fld-demo"] = "demo_uuid" @@ -98,30 +98,28 @@ def _run_action_related_model(self, steps=2, **kwargs): res = res.forms["bulk-update"].submit("apply") return res - def test_simulate(self): - res = self._run_action( - **{ - "_clean": 1, - "_validate": 1, - "select_across": 1, - "csv-header": False, - "_file": Upload( - "data.csv", - b"1,aaa,111\n2,bbb,222\n3,ccc,333", - "text/csv", - ), - "_dry_run": True, - "fld-id": "1", - "fld-char": "2", - "fld-integer": "3", - } - ) + def test_simulate(self) -> None: + res = self._run_action(**{ + "_clean": 1, + "_validate": 1, + "select_across": 1, + "csv-header": False, + "_file": Upload( + "data.csv", + b"1,aaa,111\n2,bbb,222\n3,ccc,333", + "text/csv", + ), + "_dry_run": True, + "fld-id": "1", + "fld-char": "2", + "fld-integer": "3", + }) # no changes saved on the DB assert not DemoModel.objects.filter(char="aaa", integer=111).exists() assert not DemoModel.objects.filter(char="bbb", integer=222).exists() assert res.status_code == 200 - def test_no_permission(self): + def test_no_permission(self) -> None: with user_grant_permission(self.user, ["demo.change_demomodel"]): res = self.app.get("/", user="user") res = res.click("Demo models") @@ -131,133 +129,117 @@ def test_no_permission(self): res = form.submit().follow() assert "Sorry you do not have rights to execute this action" in str(res.body) - def test_no_header(self): - self._run_action( - **{ - "_clean": 1, - "_validate": 1, - "select_across": 1, - "csv-header": False, - "_file": Upload( - "data.csv", - b"1,aaa,111\n2,bbb,222\n3,ccc,333", - "text/csv", - ), - "fld-id": "1", - "fld-char": "2", - "fld-integer": "3", - } - ) + def test_no_header(self) -> None: + self._run_action(**{ + "_clean": 1, + "_validate": 1, + "select_across": 1, + "csv-header": False, + "_file": Upload( + "data.csv", + b"1,aaa,111\n2,bbb,222\n3,ccc,333", + "text/csv", + ), + "fld-id": "1", + "fld-char": "2", + "fld-integer": "3", + }) assert DemoModel.objects.filter(char="aaa", integer=111).exists() assert DemoModel.objects.filter(char="bbb", integer=222).exists() - def test_clean_on(self): - self._run_action( - **{ - "_clean": 1, - "_validate": 1, - "select_across": 1, - "_file": Upload( - "data.csv", - b"pk,name,number\n1,aaa,111\n2,bbb,222\n3,ccc,333", - "text/csv", - ), - "fld-char": "name", - "fld-integer": "number", - } - ) + def test_clean_on(self) -> None: + self._run_action(**{ + "_clean": 1, + "_validate": 1, + "select_across": 1, + "_file": Upload( + "data.csv", + b"pk,name,number\n1,aaa,111\n2,bbb,222\n3,ccc,333", + "text/csv", + ), + "fld-char": "name", + "fld-integer": "number", + }) assert DemoModel.objects.filter(char="aaa").exists() assert DemoModel.objects.filter(char="bbb").exists() - def test_messages(self): + def test_messages(self) -> None: with user_grant_permission( self.user, ["demo.change_demomodel", "demo.adminactions_bulkupdate_demomodel"], ): - res = self._run_action( - **{ - "select_across": 1, - "_file": Upload( - "data.csv", - b"pk,name,number\n1,aaa,111\n2,bbb,222\n3,ccc,333", - "text/csv", - ), - "fld-char": "name", - "fld-integer": "number", - } - ) + res = self._run_action(**{ + "select_across": 1, + "_file": Upload( + "data.csv", + b"pk,name,number\n1,aaa,111\n2,bbb,222\n3,ccc,333", + "text/csv", + ), + "fld-char": "name", + "fld-integer": "number", + }) messages = [m.message for m in list(res.context["messages"])] - self.assertTrue(messages) + assert messages assert "Updated" in messages[0] res = self._run_action(selected_rows=[1]) messages = [m.message for m in list(res.context["messages"])] - self.assertTrue(messages) + assert messages assert "Updated" in messages[0] - def test_index_required(self): + def test_index_required(self) -> None: res = self._run_action(**{"_validate": 0, "fld-index_field": []}) assert res.status_code == 200 assert res.context["map_form"].errors == {"index_field": ["Please select one or more index fields"]} - def test_wrong_mapping(self): - res = self._run_action( - **{ - "_file": Upload( - "data.csv", - b"pk,name,number\n1,aaa,111\n2,bbb,222\n3,ccc,333", - "text/csv", - ), - "fld-index_field": ["id"], - "fld-id": "miss", - } - ) + def test_wrong_mapping(self) -> None: + res = self._run_action(**{ + "_file": Upload( + "data.csv", + b"pk,name,number\n1,aaa,111\n2,bbb,222\n3,ccc,333", + "text/csv", + ), + "fld-index_field": ["id"], + "fld-id": "miss", + }) assert res.status_code == 200 messages = [m.message for m in list(res.context["messages"])] assert messages[0] == "['miss column is not present in the file']" - def test_bulk_update_with_one_to_one_field(self): + def test_bulk_update_with_one_to_one_field(self) -> None: demo_model_instance = G(DemoModel, char="InitialValue", integer=123) demo_one_to_one_instance = G(DemoOneToOne, demo=demo_model_instance) csv_data = f"pk,one_to_one_id\n{demo_model_instance.pk},{demo_one_to_one_instance.pk}" - res = self._run_action( - **{ - "_file": Upload( - "data.csv", - csv_data.encode(), - "text/csv", - ), - "fld-onetoone": "one_to_one_id", - } - ) - self.assertTrue( - DemoModel.objects.filter(pk=demo_model_instance.pk, onetoone=demo_one_to_one_instance).exists() - ) - self.assertEqual(res.status_code, 200) + res = self._run_action(**{ + "_file": Upload( + "data.csv", + csv_data.encode(), + "text/csv", + ), + "fld-onetoone": "one_to_one_id", + }) + assert DemoModel.objects.filter(pk=demo_model_instance.pk, onetoone=demo_one_to_one_instance).exists() + assert res.status_code == 200 - def test_bulk_update_with_foreign_key(self): + def test_bulk_update_with_foreign_key(self) -> None: demo_model_instance = G(DemoModel, char="InitialValue", integer=123) demo_related_instance = G(DemoRelated, demo=demo_model_instance) new_demo_model_instance = G(DemoModel, char="NewValue", integer=456) csv_data = f"id,demo_uuid\n{demo_related_instance.pk},{new_demo_model_instance.uuid}" - res = self._run_action_related_model( - **{ - "_file": Upload( - "data.csv", - csv_data.encode(), - "text/csv", - ), - "fld-demo": "demo_uuid", - } - ) + res = self._run_action_related_model(**{ + "_file": Upload( + "data.csv", + csv_data.encode(), + "text/csv", + ), + "fld-demo": "demo_uuid", + }) - self.assertTrue( - DemoRelated.objects.filter(pk=demo_related_instance.pk, demo=new_demo_model_instance).exists() - ) - self.assertEqual(res.status_code, 200) + assert DemoRelated.objects.filter(pk=demo_related_instance.pk, demo=new_demo_model_instance).exists() + assert res.status_code == 200 class BulkUpdateMemoryFileUploadHandlerTest(BulkUpdate, TestCase): diff --git a/tests/test_byrows_update.py b/tests/test_byrows_update.py index 7516298e..a0f4725f 100644 --- a/tests/test_byrows_update.py +++ b/tests/test_byrows_update.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from demo.models import DemoModel from django.contrib.admin.options import ModelAdmin from django.contrib.admin.sites import AdminSite @@ -23,7 +25,7 @@ class TestByRowsUpdateAction(WebTestMixin, SelectRowsMixin, TestCase): _selected_rows = [0, 1] csrf_checks = False - def setUp(self): + def setUp(self) -> None: super().setUp() self._url = reverse("admin:demo_demomodel_changelist") self.user = G(User, username="user", is_staff=True, is_active=True) @@ -32,16 +34,14 @@ def setUp(self): def _get_changelist_form_response(self): res = self.app.get("/", user="user") - res = res.click("Demo models") - return res + return res.click("Demo models") def _get_action_form_response(self, change_list_response=None): form = change_list_response.forms["changelist-form"] form["action"] = "byrows_update" - res = form.submit() - return res + return form.submit() - def test_no_permission(self): + def test_no_permission(self) -> None: with user_grant_permission(self.user, ["demo.change_demomodel"]): res = self._get_changelist_form_response() @@ -51,7 +51,7 @@ def test_no_permission(self): res = form.submit().follow() assert "Sorry you do not have rights to execute this action" in str(res.body) - def test_form_rows_count(self): + def test_form_rows_count(self) -> None: """ Count the selected items appear in the action form """ @@ -65,12 +65,9 @@ def test_form_rows_count(self): form = res.forms["changelist-form"] self._select_rows(form, selected_rows=self._selected_rows) res = self._get_action_form_response(change_list_response=res) - self.assertEqual( - len(res.html.find(id="formset").find_all(class_="row")), - len(self._selected_rows), - ) + assert len(res.html.find(id="formset").find_all(class_="row")) == len(self._selected_rows) - def test_form_rows_fields_exists(self): + def test_form_rows_fields_exists(self) -> None: """ Check model fields appear in action form for each selected models """ @@ -84,7 +81,7 @@ def test_form_rows_fields_exists(self): self._select_rows(form, selected_rows=self._selected_rows) res = self._get_action_form_response(change_list_response=res) byrows_update_get_fields(ModelAdmin(DemoModel, self.site)) - for r, value in enumerate(self._selected_values): + for r, _value in enumerate(self._selected_values): for fname in byrows_update_get_fields(ModelAdmin(DemoModel, self.site)): fname = "form-%d-%s" % (r, fname) @@ -96,7 +93,7 @@ def test_form_rows_fields_exists(self): # field name upon errors assert res.forms["update-form"][fname] - def test_form_rows_edit(self): + def test_form_rows_edit(self) -> None: """ Modify a value in action form and see if its stored upon form submit """ @@ -117,4 +114,4 @@ def test_form_rows_edit(self): res.forms["update-form"].submit("apply") obj = DemoModel.objects.get(id=self._selected_values[row_to_modify]) for k, v in new_values.items(): - self.assertEqual(v, getattr(obj, k)) + assert v == getattr(obj, k) diff --git a/tests/test_duplicates.py b/tests/test_duplicates.py index 3b8093ee..ac06f391 100644 --- a/tests/test_duplicates.py +++ b/tests/test_duplicates.py @@ -1,4 +1,6 @@ # from adminactions.signals import adminaction_requested, adminaction_start, adminaction_end +from __future__ import annotations + from demo.models import DemoModel from django.contrib.auth.models import User from django.test import TestCase @@ -22,7 +24,7 @@ class FindDuplicatesTest(SelectRowsMixin, CheckSignalsMixin, WebTestMixin, TestC action_name = "find_duplicates_action" sender_model = DemoModel - def setUp(self): + def setUp(self) -> None: super().setUp() self._url = reverse("admin:demo_demomodel_changelist") self.user = G(User, username="user", is_staff=True, is_active=True) @@ -51,7 +53,7 @@ def _run_action(self, steps=2, **kwargs): res = res.form.submit("apply") return res - def test_no_permission(self): + def test_no_permission(self) -> None: with user_grant_permission(self.user, ["demo.change_demomodel"]): res = self.app.get("/", user="user") res = res.click("Demo models") @@ -61,7 +63,7 @@ def test_no_permission(self): res = form.submit().follow() assert "Sorry you do not have rights to execute this action" in str(res.body) - def test_validate_on(self): + def test_validate_on(self) -> None: self._run_action() # diff --git a/tests/test_exports.py b/tests/test_exports.py index 9f62fe30..89b368cc 100644 --- a/tests/test_exports.py +++ b/tests/test_exports.py @@ -1,24 +1,31 @@ +from __future__ import annotations + import csv import io import time import unittest +from unittest import mock from unittest.mock import Mock -import mock import xlrd from django.contrib.auth.models import User from django.test.utils import override_settings from django.utils.encoding import smart_str from django_dynamic_fixture import G from django_webtest import WebTest -from utils import CheckSignalsMixin, SelectRowsMixin, admin_register, user_grant_permission +from utils import ( + CheckSignalsMixin, + SelectRowsMixin, + admin_register, + user_grant_permission, +) __all__ = [ "ExportAsCsvTest", - "ExportAsFixtureTest", "ExportAsCsvTest", - "ExportDeleteTreeTest", + "ExportAsFixtureTest", "ExportAsXlsTest", + "ExportDeleteTreeTest", ] @@ -27,7 +34,7 @@ class ExportMixin: urls = "demo.urls" csrf_checks = True - def setUp(self): + def setUp(self) -> None: super().setUp() self.user = G(User, username="user", is_staff=True, is_active=True) @@ -37,7 +44,7 @@ class ExportAsFixtureTest(ExportMixin, SelectRowsMixin, CheckSignalsMixin, WebTe action_name = "export_as_fixture" _selected_rows = [0, 1, 2] - def test_no_permission(self): + def test_no_permission(self) -> None: with user_grant_permission(self.user, ["auth.change_user"]): res = self.app.get("/", user="user") res = res.click("Users") @@ -47,7 +54,7 @@ def test_no_permission(self): res = form.submit().follow() assert b"Sorry you do not have rights to execute this action" in res.body - def test_success(self): + def test_success(self) -> None: with user_grant_permission(self.user, ["auth.change_user", "auth.adminactions_export_user"]): res = self.app.get("/", user="user") res = res.click("Users") @@ -61,7 +68,7 @@ def test_success(self): res = res.forms["export-form"].submit("apply") assert res.json[0]["pk"] == 1 - def test_add_foreign_keys(self): + def test_add_foreign_keys(self) -> None: with user_grant_permission(self.user, ["auth.change_user", "auth.adminactions_export_user"]): res = self.app.get("/", user="user") res = res.click("Users") @@ -95,7 +102,7 @@ class ExportDeleteTreeTest(ExportMixin, SelectRowsMixin, CheckSignalsMixin, WebT action_name = "export_delete_tree" _selected_rows = [0, 1, 2] - def test_no_permission(self): + def test_no_permission(self) -> None: with user_grant_permission(self.user, ["auth.change_user"]): res = self.app.get("/", user="user") res = res.click("Users") @@ -105,7 +112,7 @@ def test_no_permission(self): res = form.submit().follow() assert b"Sorry you do not have rights to execute this action" in res.body - def test_success(self): + def test_success(self) -> None: with user_grant_permission(self.user, ["auth.change_user", "auth.adminactions_export_user"]): res = self.app.get("/", user="user") res = res.click("Users") @@ -130,28 +137,30 @@ def _run_action(self, steps=2): res = res.forms["export-form"].submit("apply") return res - def test_custom_filename(self): + def test_custom_filename(self) -> None: """ if the ModelAdmin has `get_export_as_csv_filename()` use that method to get the attachment filename """ with user_grant_permission(self.user, ["auth.change_user", "auth.adminactions_export_user"]): res = self.app.get("/", user="user") - with admin_register(User) as md: - with mock.patch.object( + with ( + admin_register(User) as md, + mock.patch.object( md, "get_export_delete_tree_filename", lambda r, q: "new.test", create=True, - ): - res = res.click("Users") - form = res.forms["changelist-form"] - form["action"] = self.action_name - form.set("_selected_action", True, 0) - form["select_across"] = 1 - res = form.submit() - res = res.forms["export-form"].submit("apply") - self.assertEqual(res.content_disposition, 'attachment;filename="new.test"') + ), + ): + res = res.click("Users") + form = res.forms["changelist-form"] + form["action"] = self.action_name + form.set("_selected_action", True, 0) + form["select_across"] = 1 + res = form.submit() + res = res.forms["export-form"].submit("apply") + assert res.content_disposition == 'attachment;filename="new.test"' class ExportAsCsvTest(ExportMixin, SelectRowsMixin, CheckSignalsMixin, WebTest): @@ -159,7 +168,7 @@ class ExportAsCsvTest(ExportMixin, SelectRowsMixin, CheckSignalsMixin, WebTest): action_name = "export_as_csv" _selected_rows = [0, 1] - def test_no_permission(self): + def test_no_permission(self) -> None: with user_grant_permission(self.user, ["auth.change_user"]): res = self.app.get("/", user="user") res = res.click("Users") @@ -169,10 +178,8 @@ def test_no_permission(self): res = form.submit().follow() assert b"Sorry you do not have rights to execute this action" in res.body - def test_success(self): - with user_grant_permission( - self.user, ["demo.change_demomodel", "demo.adminactions_export_demomodel"] - ): + def test_success(self) -> None: + with user_grant_permission(self.user, ["demo.change_demomodel", "demo.adminactions_export_demomodel"]): res = self.app.get("/", user="user") res = res.click("Demo models") form = res.forms["changelist-form"] @@ -184,30 +191,32 @@ def test_success(self): buff = io.StringIO(smart_str(res.body)) csv_reader = csv.reader(buff) - self.assertEqual(len(list(csv_reader)), 2) + assert len(list(csv_reader)) == 2 - def test_custom_filename(self): + def test_custom_filename(self) -> None: """ if the ModelAdmin has `get_export_as_csv_filename()` use that method to get the attachment filename """ with user_grant_permission(self.user, ["auth.change_user", "auth.adminactions_export_user"]): res = self.app.get("/", user="user") - with admin_register(User) as md: - with mock.patch.object( + with ( + admin_register(User) as md, + mock.patch.object( md, "get_export_as_csv_filename", lambda r, q: "new.test", create=True, - ): - res = res.click("Users") - form = res.forms["changelist-form"] - form["action"] = "export_as_csv" - form.set("_selected_action", True, 0) - form["select_across"] = 1 - res = form.submit() - res = res.forms["export-form"].submit("apply") - self.assertEqual(res.content_disposition, 'attachment;filename="new.test"') + ), + ): + res = res.click("Users") + form = res.forms["changelist-form"] + form["action"] = "export_as_csv" + form.set("_selected_action", True, 0) + form["select_across"] = 1 + res = form.submit() + res = res.forms["export-form"].submit("apply") + assert res.content_disposition == 'attachment;filename="new.test"' def _run_action(self, steps=2): with user_grant_permission(self.user, ["auth.change_user", "auth.adminactions_export_user"]): @@ -223,12 +232,12 @@ def _run_action(self, steps=2): return res @override_settings(ADMINACTIONS_STREAM_CSV=True) - def test_streaming_export(self): + def test_streaming_export(self) -> None: res = self._run_action() buff = io.StringIO(smart_str(res.body)) csv_reader = csv.reader(buff) - self.assertEqual(len(list(csv_reader)), 2) + assert len(list(csv_reader)) == 2 class ExportAsXlsTest(ExportMixin, SelectRowsMixin, CheckSignalsMixin, WebTest): @@ -250,7 +259,7 @@ def _run_action(self, step=3): res = res.forms["export-form"].submit("apply") return res - def test_no_permission(self): + def test_no_permission(self) -> None: with user_grant_permission(self.user, ["auth.change_user"]): res = self.app.get("/", user="user") res = res.click("Users") @@ -260,7 +269,7 @@ def test_no_permission(self): res = form.submit().follow() assert b"Sorry you do not have rights to execute this action" in res.body - def test_success(self): + def test_success(self) -> None: with user_grant_permission(self.user, ["auth.change_user", "auth.adminactions_export_user"]): res = self.app.get("/", user="user") res = res.click("Users") @@ -272,26 +281,24 @@ def test_success(self): self._select_rows(form) res = form.submit() res.forms["export-form"]["header"] = 1 - res.forms["export-form"]["columns"] = ["id", "username", "first_name" ""] + res.forms["export-form"]["columns"] = ["id", "username", "first_name"] res = res.forms["export-form"].submit("apply") buff = io.BytesIO(res.body) buff.seek(0) w = xlrd.open_workbook(file_contents=buff.read()) sheet = w.sheet_by_index(0) - self.assertEqual(sheet.cell_value(0, 0), "#") - self.assertEqual(sheet.cell_value(0, 1), "ID") - self.assertEqual(sheet.cell_value(0, 2), "username") - self.assertEqual(sheet.cell_value(0, 3), "first name") - self.assertEqual(sheet.cell_value(1, 1), 1.0) - self.assertEqual(sheet.cell_value(1, 2), "sax") - self.assertEqual(sheet.cell_value(2, 2), "user") + assert sheet.cell_value(0, 0) == "#" + assert sheet.cell_value(0, 1) == "ID" + assert sheet.cell_value(0, 2) == "username" + assert sheet.cell_value(0, 3) == "first name" + assert sheet.cell_value(1, 1) == 1.0 + assert sheet.cell_value(1, 2) == "sax" + assert sheet.cell_value(2, 2) == "user" # self.assertEqual(sheet.cell_value(3, 2), u'user_00') - def test_use_display_ok(self): - with user_grant_permission( - self.user, ["demo.change_demomodel", "demo.adminactions_export_demomodel"] - ): + def test_use_display_ok(self) -> None: + with user_grant_permission(self.user, ["demo.change_demomodel", "demo.adminactions_export_demomodel"]): res = self.app.get("/", user="user") res = res.click("Demo models") form = res.forms["changelist-form"] @@ -304,7 +311,7 @@ def test_use_display_ok(self): "char", "text", "bigint", - "choices" "", + "choices", ] res = res.forms["export-form"].submit("apply") buff = io.BytesIO(res.body) @@ -312,19 +319,17 @@ def test_use_display_ok(self): buff.seek(0) w = xlrd.open_workbook(file_contents=buff.read()) sheet = w.sheet_by_index(0) - self.assertEqual(sheet.cell_value(0, 1), "Chäř") - self.assertEqual(sheet.cell_value(0, 2), "bigint") - self.assertEqual(sheet.cell_value(0, 3), "text") - self.assertEqual(sheet.cell_value(0, 4), "choices") - self.assertEqual(sheet.cell_value(1, 1), "Pizzä ïs Gööd") - self.assertEqual(sheet.cell_value(1, 2), 333333333.0) - self.assertEqual(sheet.cell_value(1, 3), "lorem ipsum") - self.assertEqual(sheet.cell_value(1, 4), "Choice 2") - - def test_use_display_ko(self): - with user_grant_permission( - self.user, ["demo.change_demomodel", "demo.adminactions_export_demomodel"] - ): + assert sheet.cell_value(0, 1) == "Chäř" + assert sheet.cell_value(0, 2) == "bigint" + assert sheet.cell_value(0, 3) == "text" + assert sheet.cell_value(0, 4) == "choices" + assert sheet.cell_value(1, 1) == "Pizzä ïs Gööd" + assert sheet.cell_value(1, 2) == 333333333.0 + assert sheet.cell_value(1, 3) == "lorem ipsum" + assert sheet.cell_value(1, 4) == "Choice 2" + + def test_use_display_ko(self) -> None: + with user_grant_permission(self.user, ["demo.change_demomodel", "demo.adminactions_export_demomodel"]): res = self.app.get("/", user="user") res = res.click("Demo models") form = res.forms["changelist-form"] @@ -336,7 +341,7 @@ def test_use_display_ko(self): "char", "text", "bigint", - "choices" "", + "choices", ] res = res.forms["export-form"].submit("apply") buff = io.BytesIO(res.body) @@ -344,19 +349,17 @@ def test_use_display_ko(self): buff.seek(0) w = xlrd.open_workbook(file_contents=buff.read()) sheet = w.sheet_by_index(0) - self.assertEqual(sheet.cell_value(0, 1), "Chäř") - self.assertEqual(sheet.cell_value(0, 2), "bigint") - self.assertEqual(sheet.cell_value(0, 3), "text") - self.assertEqual(sheet.cell_value(0, 4), "choices") - self.assertEqual(sheet.cell_value(1, 1), "Pizzä ïs Gööd") - self.assertEqual(sheet.cell_value(1, 2), 333333333.0) - self.assertEqual(sheet.cell_value(1, 3), "lorem ipsum") - self.assertEqual(sheet.cell_value(1, 4), 2.0) - - def test_unicode(self): - with user_grant_permission( - self.user, ["demo.change_demomodel", "demo.adminactions_export_demomodel"] - ): + assert sheet.cell_value(0, 1) == "Chäř" + assert sheet.cell_value(0, 2) == "bigint" + assert sheet.cell_value(0, 3) == "text" + assert sheet.cell_value(0, 4) == "choices" + assert sheet.cell_value(1, 1) == "Pizzä ïs Gööd" + assert sheet.cell_value(1, 2) == 333333333.0 + assert sheet.cell_value(1, 3) == "lorem ipsum" + assert sheet.cell_value(1, 4) == 2.0 + + def test_unicode(self) -> None: + with user_grant_permission(self.user, ["demo.change_demomodel", "demo.adminactions_export_demomodel"]): res = self.app.get("/", user="user") res = res.click("Demo models") form = res.forms["changelist-form"] @@ -373,14 +376,12 @@ def test_unicode(self): buff.seek(0) w = xlrd.open_workbook(file_contents=buff.read()) sheet = w.sheet_by_index(0) - self.assertEqual(sheet.cell_value(0, 1), "Chäř") - self.assertEqual(sheet.cell_value(1, 1), "Pizzä ïs Gööd") + assert sheet.cell_value(0, 1) == "Chäř" + assert sheet.cell_value(1, 1) == "Pizzä ïs Gööd" - def test_issue_93(self): + def test_issue_93(self) -> None: # default date(time) format in XLS export doesn't import well on excel - with user_grant_permission( - self.user, ["demo.change_demomodel", "demo.adminactions_export_demomodel"] - ): + with user_grant_permission(self.user, ["demo.change_demomodel", "demo.adminactions_export_demomodel"]): res = self.app.get("/", user="user") res = res.click("Demo models") form = res.forms["changelist-form"] @@ -403,18 +404,18 @@ def test_issue_93(self): format_key = fmt.format_key format = w.format_map[format_key] # gets a Format object - self.assertEqual(cell.value, 41303.0) - self.assertEqual(cell.ctype, 3) - self.assertEqual(format.format_str, "d/m/Y") + assert cell.value == 41303.0 + assert cell.ctype == 3 + assert format.format_str == "d/m/Y" @unittest.skip("Impossible to reliably time different machine runs") - def test_faster_export(self): + def test_faster_export(self) -> None: # generate 3k users start = time.time() user_count = User.objects.count() - User.objects.bulk_create([User(username="bulk_user_%s" % i) for i in range(3000)]) + User.objects.bulk_create([User(username=f"bulk_user_{i}") for i in range(3000)]) # print('created 3k users in %.1f seconds' % (time.time() - start)) - self.assertEqual(User.objects.count(), 3000 + user_count) + assert User.objects.count() == 3000 + user_count start = time.time() with user_grant_permission(self.user, ["auth.change_user", "auth.adminactions_export_user"]): @@ -437,14 +438,10 @@ def test_faster_export(self): w = xlrd.open_workbook(file_contents=buff.read()) sheet = w.sheet_by_index(0) - self.assertEqual(sheet.nrows, 3000 + user_count + 1) - self.assertLessEqual( - res_time, - 6.5, - "Response should return under 6.5 " "seconds, was %.2f" % res_time, - ) + assert sheet.nrows == 3000 + user_count + 1 + assert res_time <= 6.5, f"Response should return under 6.5 seconds, was {res_time:.2f}" - def test_modeladmin_attributes(self): + def test_modeladmin_attributes(self) -> None: from demo.models import DemoModel from django.contrib.admin import site diff --git a/tests/test_graph.py b/tests/test_graph.py index ab891e20..9e0c7bec 100644 --- a/tests/test_graph.py +++ b/tests/test_graph.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from django.contrib.auth.models import User from django.urls import reverse from django_dynamic_fixture import G @@ -12,7 +14,7 @@ class TestGraph(SelectRowsMixin, CheckSignalsMixin, WebTest): action_name = "graph_queryset" _selected_rows = [0, 1] - def setUp(self): + def setUp(self) -> None: super().setUp() self.user = G(User, username="user", is_staff=True, is_active=True) @@ -33,24 +35,24 @@ def _run_action(self, steps=2): return res - def test_graph_apply(self): + def test_graph_apply(self) -> None: url = reverse("admin:auth_user_changelist") res = self.app.get(url, user="sax") form = res.forms["changelist-form"] form["action"] = "graph_queryset" - for i in range(0, 11): + for i in range(11): form.set("_selected_action", True, i) res = form.submit() res.forms["charts-form"]["graph_type"] = "PieChart" res.forms["charts-form"]["axes_x"] = "is_staff" res = res.forms["charts-form"].submit("apply") - def test_graph_post(self): + def test_graph_post(self) -> None: url = reverse("admin:auth_user_changelist") res = self.app.get(url, user="sax") form = res.forms["changelist-form"] form["action"] = "graph_queryset" - for i in range(0, 11): + for i in range(11): form.set("_selected_action", True, i) res = form.submit() res.forms["charts-form"]["graph_type"] = "PieChart" diff --git a/tests/test_mass_update.py b/tests/test_mass_update.py index e55133eb..80ac1dcd 100644 --- a/tests/test_mass_update.py +++ b/tests/test_mass_update.py @@ -1,9 +1,16 @@ # from adminactions.signals import adminaction_requested, adminaction_start, adminaction_end +from __future__ import annotations + from pathlib import Path from unittest import skipIf from unittest.mock import patch -from demo.models import DemoModel, DemoModelAdmin, DemoModelMassUpdateForm, TestMassUpdateForm +from demo.models import ( + DemoModel, + DemoModelAdmin, + DemoModelMassUpdateForm, + TestMassUpdateForm, +) from django.conf import settings from django.contrib.auth.models import User from django.db.models import fields @@ -24,12 +31,12 @@ ] -def test_operationmanager_get(): +def test_operationmanager_get() -> None: assert OPERATIONS[fields.IntegerField] == OPERATIONS[fields.BigIntegerField] assert OPERATIONS[fields.BooleanField] == OPERATIONS[fields.NullBooleanField] -def test_operationmanager_get_for_field(): +def test_operationmanager_get_for_field() -> None: assert list(OPERATIONS[fields.CharField].keys()) == [ "set", "set null", @@ -58,7 +65,7 @@ class MassUpdateTest(SelectRowsMixin, CheckSignalsMixin, WebTestMixin, TestCase) action_name = "mass_update" sender_model = DemoModel - def setUp(self): + def setUp(self) -> None: super().setUp() self._url = reverse("admin:demo_demomodel_changelist") self.user = G(User, username="user", is_staff=True, is_active=True) @@ -87,7 +94,7 @@ def _run_action(self, steps=2, **kwargs): res = res.forms["mass-update-form"].submit("apply") return res - def test_no_permission(self): + def test_no_permission(self) -> None: with user_grant_permission(self.user, ["demo.change_demomodel"]): res = self.app.get("/", user="user") res = res.click("Demo models") @@ -97,7 +104,7 @@ def test_no_permission(self): res = form.submit().follow() assert "Sorry you do not have rights to execute this action" in str(res.body) - def test_custom_modeladmin_form(self): + def test_custom_modeladmin_form(self) -> None: DemoModelAdmin.mass_update_form = DemoModelMassUpdateForm with user_grant_permission( self.user, @@ -112,7 +119,7 @@ def test_custom_modeladmin_form(self): assert isinstance(res.context["adminform"].form, DemoModelMassUpdateForm) - def test_custom_form(self): + def test_custom_form(self) -> None: with override_settings(AA_MASSUPDATE_FORM="demo.models.TestMassUpdateForm"): config.AA_MASSUPDATE_FORM = settings.AA_MASSUPDATE_FORM with user_grant_permission( @@ -129,44 +136,44 @@ def test_custom_form(self): config.AA_MASSUPDATE_FORM = "adminactions.mass_update.MassUpdateForm" assert isinstance(res.context["adminform"].form, TestMassUpdateForm) - def test_validate_on(self): - self._run_action(**{"_validate": 1}) + def test_validate_on(self) -> None: + self._run_action(_validate=1) assert DemoModel.objects.filter(char="CCCCC").exists() assert not DemoModel.objects.filter(char="ccccc").exists() - def test_validate_off(self): - res = self._run_action(**{"_validate": 0}) + def test_validate_off(self) -> None: + res = self._run_action(_validate=0) assert res.status_code == 200 form = res.context["adminform"].form assert form.errors["__all__"] == ["Cannot use operators without 'validate'"] - def test_clean_on(self): - self._run_action(**{"_clean": 1}) + def test_clean_on(self) -> None: + self._run_action(_clean=1) assert DemoModel.objects.filter(char="CCCCC").exists() assert not DemoModel.objects.filter(char="ccccc").exists() - def test_messages(self): + def test_messages(self) -> None: with user_grant_permission( self.user, ["demo.change_demomodel", "demo.adminactions_massupdate_demomodel"], ): - res = self._run_action(**{"_clean": 1}) + res = self._run_action(_clean=1) res = res.follow() messages = [m.message for m in list(res.context["messages"])] - self.assertTrue(messages) - self.assertEqual("Updated 2 records", messages[0]) + assert messages + assert messages[0] == "Updated 2 records" res = self._run_action(selected_rows=[1]).follow() messages = [m.message for m in list(res.context["messages"])] - self.assertTrue(messages) - self.assertEqual("Updated 1 records", messages[0]) + assert messages + assert messages[0] == "Updated 1 records" @skipIf(not celery_present, "Celery not installed") - def test_async_qs(self): + def test_async_qs(self) -> None: # Create handler - res = self._run_action(**{"_async": 1, "_validate": 0, "chk_id_char": False}) + res = self._run_action(_async=1, _validate=0, chk_id_char=False) assert res.status_code == 302 assert DemoModel.objects.filter(choices=1).exists() @@ -174,8 +181,8 @@ def test_async_qs(self): @patch("adminactions.mass_update.adminaction_start.send") @patch("adminactions.mass_update.adminaction_requested.send") @skipIf(not celery_present, "Celery not installed") - def test_async_single(self, req, start, end): - res = self._run_action(**{"_async": 1, "_validate": 1}) + def test_async_single(self, req, start, end) -> None: + res = self._run_action(_async=1, _validate=1) assert res.status_code == 302 assert req.called assert start.called @@ -183,26 +190,16 @@ def test_async_single(self, req, start, end): assert DemoModel.objects.filter(char="CCCCC").exists() assert not DemoModel.objects.filter(char="ccccc").exists() - def test_file_field(self): + def test_file_field(self) -> None: self._run_action( - **{ - "_validate": 1, - "select_across": 1, - "chk_id_image": True, - "image": Upload(str(Path(__file__).parent / "test.jpeg")), - } + _validate=1, select_across=1, chk_id_image=True, image=Upload(str(Path(__file__).parent / "test.jpeg")) ) obj1 = DemoModel.objects.get(pk=1) obj2 = DemoModel.objects.get(pk=2) assert obj1.image.read() == obj2.image.read() - def test_file_field_prevent_async(self): + def test_file_field_prevent_async(self) -> None: res = self._run_action( - **{ - "_async": 1, - "select_across": 1, - "chk_id_image": True, - "image": Upload(str(Path(__file__).parent / "test.jpeg")), - } + _async=1, select_across=1, chk_id_image=True, image=Upload(str(Path(__file__).parent / "test.jpeg")) ) assert res.status_code == 200 diff --git a/tests/test_merge.py b/tests/test_merge.py index e92bdfe9..aa3c9312 100644 --- a/tests/test_merge.py +++ b/tests/test_merge.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import os from demo.models import DemoModel, DemoOneToOne, UserDetail @@ -22,58 +24,58 @@ def get_profile(user): class MergeTestApi(BaseTestCaseMixin, TestCase): fixtures = ["adminactions.json", "demoproject.json"] - def setUp(self): + def setUp(self) -> None: super().setUp() self.master_pk = 2 self.other_pk = 3 - def tearDown(self): + def tearDown(self) -> None: super().tearDown() - def test_merge_success_no_commit(self): + def test_merge_success_no_commit(self) -> None: master = User.objects.get(pk=self.master_pk) other = User.objects.get(pk=self.other_pk) result = merge(master, other) - self.assertTrue(User.objects.filter(pk=master.pk).exists()) - self.assertTrue(User.objects.filter(pk=other.pk).exists()) + assert User.objects.filter(pk=master.pk).exists() + assert User.objects.filter(pk=other.pk).exists() - self.assertEqual(result.pk, master.pk) - self.assertEqual(result.first_name, master.first_name) - self.assertEqual(result.last_name, master.last_name) - self.assertEqual(result.password, master.password) + assert result.pk == master.pk + assert result.first_name == master.first_name + assert result.last_name == master.last_name + assert result.password == master.password - def test_merge_success_fields_no_commit(self): + def test_merge_success_fields_no_commit(self) -> None: master = User.objects.get(pk=self.master_pk) other = User.objects.get(pk=self.other_pk) result = merge(master, other, ["password", "last_login"]) master = User.objects.get(pk=master.pk) - self.assertTrue(User.objects.filter(pk=master.pk).exists()) - self.assertTrue(User.objects.filter(pk=other.pk).exists()) + assert User.objects.filter(pk=master.pk).exists() + assert User.objects.filter(pk=other.pk).exists() - self.assertNotEqual(result.last_login, master.last_login) - self.assertEqual(result.last_login, other.last_login) - self.assertEqual(result.password, other.password) + assert result.last_login != master.last_login + assert result.last_login == other.last_login + assert result.password == other.password - self.assertNotEqual(result.last_name, other.last_name) + assert result.last_name != other.last_name - def test_merge_success_commit(self): + def test_merge_success_commit(self) -> None: old_master = User.objects.get(pk=self.master_pk) other = User.objects.get(pk=self.other_pk) result = merge(old_master, other, commit=True) master = User.objects.get(pk=result.pk) # reload - self.assertTrue(User.objects.filter(pk=master.pk).exists()) - self.assertFalse(User.objects.filter(pk=other.pk).exists()) + assert User.objects.filter(pk=master.pk).exists() + assert not User.objects.filter(pk=other.pk).exists() - self.assertEqual(result.pk, master.pk) - self.assertEqual(master.first_name, old_master.first_name) - self.assertEqual(master.last_name, old_master.last_name) - self.assertEqual(master.password, old_master.password) + assert result.pk == master.pk + assert master.first_name == old_master.first_name + assert master.last_name == old_master.last_name + assert master.password == old_master.password - def test_merge_success_m2m(self): + def test_merge_success_m2m(self) -> None: master = User.objects.get(pk=self.master_pk) other = User.objects.get(pk=self.other_pk) group = Group.objects.get_or_create(name="G1")[0] @@ -84,7 +86,7 @@ def test_merge_success_m2m(self): master = User.objects.get(pk=result.pk) # reload self.assertSequenceEqual(master.groups.all(), [group]) - def test_merge_success_m2m_all(self): + def test_merge_success_m2m_all(self) -> None: master = User.objects.get(pk=self.master_pk) other = User.objects.get(pk=self.other_pk) group = Group.objects.get_or_create(name="G1")[0] @@ -98,7 +100,7 @@ def test_merge_success_m2m_all(self): self.assertSequenceEqual(master.groups.all(), [group]) self.assertSequenceEqual(master.user_permissions.all(), [perm]) - def test_merge_success_related_all(self): + def test_merge_success_related_all(self) -> None: master = User.objects.get(pk=self.master_pk) other = User.objects.get(pk=self.other_pk) entry = other.logentry_set.get_or_create(object_repr="test", action_flag=1)[0] @@ -107,9 +109,9 @@ def test_merge_success_related_all(self): master = User.objects.get(pk=result.pk) # reload self.assertSequenceEqual(master.logentry_set.all(), [entry]) - self.assertTrue(LogEntry.objects.filter(pk=entry.pk).exists()) + assert LogEntry.objects.filter(pk=entry.pk).exists() - def test_merge_one_to_one_move_single(self): + def test_merge_one_to_one_move_single(self) -> None: master = DemoModel.objects.get(pk=1) other = DemoModel.objects.get(pk=2) related_one = DemoOneToOne(demo=other) @@ -118,12 +120,12 @@ def test_merge_one_to_one_move_single(self): result = merge(master, other, commit=True, related=ALL_FIELDS) master = DemoModel.objects.get(pk=result.pk) # reload - self.assertEqual(master.onetoone, related_one) - self.assertTrue(DemoOneToOne.objects.filter(pk=related_one.pk).exists()) - self.assertEqual(os.path.basename(master.image.file.name), "second.png") + assert master.onetoone == related_one + assert DemoOneToOne.objects.filter(pk=related_one.pk).exists() + assert os.path.basename(master.image.file.name) == "second.png" # @skipIf(not hasattr(settings, 'AUTH_PROFILE_MODULE'), "") - def test_merge_one_to_one_field(self): + def test_merge_one_to_one_field(self) -> None: master = User.objects.get(pk=self.master_pk) other = User.objects.get(pk=self.other_pk) profile = get_profile(other) @@ -134,11 +136,11 @@ def test_merge_one_to_one_field(self): master = User.objects.get(pk=result.pk) # reload self.assertSequenceEqual(master.logentry_set.all(), [entry]) - self.assertTrue(LogEntry.objects.filter(pk=entry.pk).exists()) - self.assertEqual(get_profile(result), profile) + assert LogEntry.objects.filter(pk=entry.pk).exists() + assert get_profile(result) == profile # self.assertEqual(master.get_profile(), profile) - def test_merge_ignore_related(self): + def test_merge_ignore_related(self) -> None: master = User.objects.get(pk=self.master_pk) other = User.objects.get(pk=self.other_pk) entry = other.logentry_set.get_or_create(object_repr="test", action_flag=1)[0] @@ -146,10 +148,10 @@ def test_merge_ignore_related(self): master = User.objects.get(pk=result.pk) # reload self.assertSequenceEqual(master.logentry_set.all(), []) - self.assertFalse(User.objects.filter(pk=other.pk).exists()) - self.assertFalse(LogEntry.objects.filter(pk=entry.pk).exists()) + assert not User.objects.filter(pk=other.pk).exists() + assert not LogEntry.objects.filter(pk=entry.pk).exists() - def test_merge_image(self): + def test_merge_image(self) -> None: master = DemoModel.objects.get(pk=3) other = DemoModel.objects.get(pk=1) img1 = other.image @@ -167,9 +169,9 @@ def test_merge_image(self): ) master = DemoModel.objects.get(pk=result.pk) # reload - self.assertFalse(DemoModel.objects.filter(pk=other.pk).exists()) - self.assertEqual(master.image, img1) - self.assertEqual(master.subclassed_image, img2) + assert not DemoModel.objects.filter(pk=other.pk).exists() + assert master.image == img1 + assert master.subclassed_image == img2 class TestMergeAction(SelectRowsMixin, WebTestMixin, TestCase): @@ -180,7 +182,7 @@ class TestMergeAction(SelectRowsMixin, WebTestMixin, TestCase): action_name = "merge" _selected_rows = [1, 2] - def setUp(self): + def setUp(self) -> None: super().setUp() self.url = reverse("admin:auth_user_changelist") self.user = G(User, username="user", is_staff=True, is_active=True) @@ -212,7 +214,7 @@ def _run_action(self, steps=3, page_start=None): res = res.forms["merge-form"].submit("apply") return res - def test_no_permission(self): + def test_no_permission(self) -> None: with user_grant_permission(self.user, ["auth.change_user"]): res = self.app.get("/", user="user") res = res.click("Users") @@ -223,7 +225,7 @@ def test_no_permission(self): assert "Sorry you do not have rights to execute this action" in str(res.body) # noinspection PyTypeChecker - def test_success(self): + def test_success(self) -> None: res = self._run_action(1) preserved = User.objects.get(pk=self._selected_values[0]) removed = User.objects.get(pk=self._selected_values[1]) @@ -232,14 +234,14 @@ def test_success(self): self._run_action([2, 3], res) - self.assertFalse(User.objects.filter(pk=removed.pk).exists()) - self.assertTrue(User.objects.filter(pk=preserved.pk).exists()) + assert not User.objects.filter(pk=removed.pk).exists() + assert User.objects.filter(pk=preserved.pk).exists() preserved_after = User.objects.get(pk=self._selected_values[0]) - self.assertEqual(preserved_after.email, removed.email) - self.assertFalse(LogEntry.objects.filter(pk=removed.pk).exists()) + assert preserved_after.email == removed.email + assert not LogEntry.objects.filter(pk=removed.pk).exists() - def test_error_if_too_many_records(self): + def test_error_if_too_many_records(self) -> None: with user_grant_permission(self.user, ["auth.change_user", "auth.adminactions_merge_user"]): res = self.app.get("/", user="user") res = res.click("Users") @@ -249,7 +251,7 @@ def test_error_if_too_many_records(self): res = form.submit().follow() self.assertContains(res, "Please select exactly 2 records") - def test_swap(self): + def test_swap(self) -> None: with user_grant_permission(self.user, ["auth.change_user", "auth.adminactions_merge_user"]): # removed = User.objects.get(pk=self._selected_rows[0]) # preserved = User.objects.get(pk=self._selected_rows[1]) @@ -279,13 +281,13 @@ def test_swap(self): res = res.forms["merge-form"].submit("apply") preserved_after = User.objects.get(pk=self._selected_values[1]) - self.assertFalse(User.objects.filter(pk=removed.pk).exists()) - self.assertTrue(User.objects.filter(pk=preserved.pk).exists()) + assert not User.objects.filter(pk=removed.pk).exists() + assert User.objects.filter(pk=preserved.pk).exists() - self.assertEqual(preserved_after.email, removed.email) - self.assertFalse(LogEntry.objects.filter(pk=removed.pk).exists()) + assert preserved_after.email == removed.email + assert not LogEntry.objects.filter(pk=removed.pk).exists() - def test_merge_move_detail(self): + def test_merge_move_detail(self) -> None: from adminactions.merge import MergeForm with user_grant_permission(self.user, ["auth.change_user", "auth.adminactions_merge_user"]): @@ -318,10 +320,10 @@ def test_merge_move_detail(self): res = res.forms["merge-form"].submit("apply") preserved_after = User.objects.get(pk=self._selected_values[1]) - self.assertEqual(preserved_after.userdetail_set.count(), 2) - self.assertFalse(User.objects.filter(pk=removed.pk).exists()) + assert preserved_after.userdetail_set.count() == 2 + assert not User.objects.filter(pk=removed.pk).exists() - def test_merge_delete_detail(self): + def test_merge_delete_detail(self) -> None: from adminactions.merge import MergeForm with user_grant_permission(self.user, ["auth.change_user", "auth.adminactions_merge_user"]): @@ -354,8 +356,8 @@ def test_merge_delete_detail(self): res = res.forms["merge-form"].submit("apply") preserved_after = User.objects.get(pk=self._selected_values[1]) - self.assertEqual(preserved_after.userdetail_set.count(), 1) - self.assertFalse(User.objects.filter(pk=removed.pk).exists()) + assert preserved_after.userdetail_set.count() == 1 + assert not User.objects.filter(pk=removed.pk).exists() class TestMergeImageAction(SelectRowsMixin, WebTestMixin, TestCase): @@ -366,7 +368,7 @@ class TestMergeImageAction(SelectRowsMixin, WebTestMixin, TestCase): action_name = "merge" _selected_rows = [0, 2] - def setUp(self): + def setUp(self) -> None: super().setUp() self.url = reverse("admin:demo_demomodel_changelist") self.user = G(User, username="user", is_staff=True, is_active=True) @@ -398,7 +400,7 @@ def _run_action(self, steps=3, page_start=None): return res # noinspection PyTypeChecker - def test_success(self): + def test_success(self) -> None: res = self._run_action(1) preserved = DemoModel.objects.get(pk=self._selected_values[0]) removed = DemoModel.objects.get(pk=self._selected_values[1]) @@ -413,8 +415,8 @@ def test_success(self): self._run_action([2, 3], res) - self.assertFalse(DemoModel.objects.filter(pk=removed.pk).exists()) - self.assertTrue(DemoModel.objects.filter(pk=preserved.pk).exists()) + assert not DemoModel.objects.filter(pk=removed.pk).exists() + assert DemoModel.objects.filter(pk=preserved.pk).exists() preserved_after = DemoModel.objects.get(pk=preserved.pk) diff --git a/tests/test_permissions.py b/tests/test_permissions.py index 36da5c7b..45822fd5 100644 --- a/tests/test_permissions.py +++ b/tests/test_permissions.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import logging import pytest @@ -20,8 +22,8 @@ "mass_update", ], ) -@pytest.mark.django_db() -def test_permission_needed(app, admin, demomodels, action): +@pytest.mark.django_db +def test_permission_needed(app, admin, demomodels, action) -> None: permission_mapping = { "export_as_csv": "adminactions_export", "export_as_fixture": "adminactions_export", @@ -31,7 +33,7 @@ def test_permission_needed(app, admin, demomodels, action): "merge": "adminactions_merge", "graph_queryset": "adminactions_chart", } - perm = "demo.{}_demomodel".format(permission_mapping[action]) + perm = f"demo.{permission_mapping[action]}_demomodel" url = reverse("admin:demo_demomodel_changelist") pks = [demomodels[0].pk, demomodels[1].pk] with user_grant_permission(admin, ["demo.change_demomodel"]): @@ -44,9 +46,7 @@ def test_permission_needed(app, admin, demomodels, action): ) assert res.status_code == 302 res = res.follow() - assert "Sorry you do not have rights to execute this action" in [ - str(m) for m in res.context["messages"] - ] + assert "Sorry you do not have rights to execute this action" in [str(m) for m in res.context["messages"]] with user_grant_permission(admin, [perm]): res = app.post( @@ -59,9 +59,9 @@ def test_permission_needed(app, admin, demomodels, action): assert res.status_code == 200 -@pytest.mark.django_db() -def test_permissions(admin): +@pytest.mark.django_db +def test_permissions(admin) -> None: assert Permission.objects.filter(codename__startswith="adminactions").count() == 70 with user_grant_permission(admin, ["demo.adminactions_export_demomodel"]): - assert admin.get_all_permissions() == set(["demo.adminactions_export_demomodel"]) + assert admin.get_all_permissions() == {"demo.adminactions_export_demomodel"} diff --git a/tests/test_templatetags.py b/tests/test_templatetags.py index 75f4bbe3..a80b7485 100644 --- a/tests/test_templatetags.py +++ b/tests/test_templatetags.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pytest from adminactions.templatetags.massupdate import fields_values, link_fields_values @@ -12,11 +14,11 @@ ], ids=("list", "str", "int"), ) -def test_link_fields_values(data): +def test_link_fields_values(data) -> None: assert link_fields_values(data, "field1") -def test_fields_values(): +def test_fields_values() -> None: data = { "name1": ["value1.1", "value1.2"], "name2": ["value2.1", "value2.2"], diff --git a/tests/test_transaction.py b/tests/test_transaction.py index aa8b7a1d..78a38a2b 100644 --- a/tests/test_transaction.py +++ b/tests/test_transaction.py @@ -1,28 +1,34 @@ -import mock +from __future__ import annotations + +from typing import NoReturn +from unittest import mock + import pytest from django.contrib.auth.models import Group, User from django.db import IntegrityError from django.db.transaction import atomic from django.test import TransactionTestCase +from django.urls.base import reverse from django_dynamic_fixture import G from adminactions import compat from adminactions.api import merge +from adminactions.compat import nocommit from adminactions.exceptions import ActionInterrupted from adminactions.signals import adminaction_end pytestmarker = pytest.mark.skip -@pytest.mark.django_db() -def test_nocommit(): - with compat.nocommit(): +@pytest.mark.django_db +def test_nocommit() -> None: + with nocommit(): G(Group, name="name") assert not Group.objects.filter(name="name").exists() -@pytest.mark.django_db() -def test_transaction_merge(users): +@pytest.mark.django_db +def test_transaction_merge(users) -> None: master, other = users with atomic(): with mock.patch("django.contrib.auth.models.User.delete", side_effect=IntegrityError): @@ -35,15 +41,15 @@ def test_transaction_merge(users): assert master.first_name != other.first_name -@pytest.mark.django_db() -def test_transaction_mass_update(app, users, administrator): +@pytest.mark.django_db +def test_transaction_mass_update(app, users, administrator) -> None: assert User.objects.filter(is_staff=True).count() == 1 # sanity check - def _handler(*args, **kwargs): - raise ActionInterrupted() + def _handler(*args, **kwargs) -> NoReturn: + raise ActionInterrupted with atomic(): - res = app.get("/admin/", user=administrator.username) + res = app.get(reverse("admin:index"), user=administrator.username) res = res.click("Users") form = res.forms["changelist-form"] form["action"] = "mass_update" @@ -69,5 +75,5 @@ def _handler(*args, **kwargs): class TestIsLibero(TransactionTestCase): - def test_true(self): - self.assertTrue(True) + def test_true(self) -> None: + assert True diff --git a/tests/test_utils.py b/tests/test_utils.py index b3322f7f..9db0503f 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,9 +1,11 @@ +from __future__ import annotations + import pytest from adminactions.utils import get_field_by_name, get_verbose_name -def test_get_verbose_name(): +def test_get_verbose_name() -> None: from django.contrib.auth.models import Permission, User user = User() @@ -27,7 +29,7 @@ def test_get_verbose_name(): get_verbose_name(p, None) -def test_flatten(): +def test_flatten() -> None: from adminactions.utils import flatten assert flatten([[[1, 2, 3], (42, None)], [4, 5], [6], 7, (8, 9, 10)]) == [ diff --git a/tests/test_views.py b/tests/test_views.py index 2aeffb74..cde23929 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import datetime import pytest @@ -6,15 +8,15 @@ from django.utils.encoding import smart_str -@pytest.mark.django_db() -def test_format_date(app): +@pytest.mark.django_db +def test_format_date(app) -> None: d = datetime.datetime.now() url = reverse("adminactions.format_date") fmt = "d-m-Y" - res = app.get("{}?fmt={}".format(url, fmt)) + res = app.get(f"{url}?fmt={fmt}") assert smart_str(res.body) == dateformat.format(d, fmt) fmt = "d mm Y" - res = app.get("{}?fmt={}".format(url, fmt)) + res = app.get(f"{url}?fmt={fmt}") assert smart_str(res.body) == dateformat.format(d, fmt) diff --git a/tests/utils.py b/tests/utils.py index ab0015ef..3fc2e220 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,6 +1,9 @@ +from __future__ import annotations + import os import string from random import choice, randrange, shuffle +from typing import NoReturn from django.conf import global_settings from django.contrib import admin @@ -13,11 +16,15 @@ from django_dynamic_fixture.fixture_algorithms.random_fixture import RandomDataFixture from adminactions.exceptions import ActionInterrupted -from adminactions.signals import adminaction_end, adminaction_requested, adminaction_start +from adminactions.signals import ( + adminaction_end, + adminaction_requested, + adminaction_start, +) class admin_register: - def __init__(self, model, model_admin=None, unregister=False): + def __init__(self, model, model_admin=None, unregister=False) -> None: self.model = model self.model_admin = model_admin self.unregister = unregister @@ -36,8 +43,7 @@ def __exit__(self, *exc_info): def start(self): """Activate a patch, returning any created mock.""" - result = self.__enter__() - return result + return self.__enter__() def stop(self): """Stop an active patch.""" @@ -63,7 +69,8 @@ def get_group(name=None, permissions=None): try: app_label, codename = permission_name.split(".") except ValueError: - raise ValueError("Invalid permission name `{0}`".format(permission_name)) + msg = f"Invalid permission name `{permission_name}`" + raise ValueError(msg) __, model_name = codename.rsplit("_", 1) ct = ContentType.objects.get(app_label__iexact=app_label, model__iexact=model_name) permission = Permission.objects.get(content_type=ct, codename=codename) @@ -72,7 +79,7 @@ def get_group(name=None, permissions=None): class user_grant_permission: - def __init__(self, user, permissions=None): + def __init__(self, user, permissions=None) -> None: self.user = user self.permissions = permissions self.group = None @@ -92,8 +99,7 @@ def __exit__(self, *exc_info): def start(self): """Activate a patch, returning any created mock.""" - result = self.__enter__() - return result + return self.__enter__() def stop(self): """Stop an active patch.""" @@ -105,7 +111,7 @@ class SelectRowsMixin: _selected_values = [] csrf_checks = False - def _select_rows(self, form, selected_rows=None): + def _select_rows(self, form, selected_rows=None) -> None: if selected_rows is None: selected_rows = self._selected_rows @@ -120,11 +126,11 @@ def _select_rows(self, form, selected_rows=None): class CheckSignalsMixin: MESSAGE = "Action Interrupted Test" - def test_signal_sent(self): + def test_signal_sent(self) -> None: def handler_factory(name): - def myhandler(sender, action, request, queryset, **kwargs): + def myhandler(sender, action, request, queryset, **kwargs) -> None: handler_factory.invoked[name] = True - self.assertEqual(action, self.action_name) + assert action == self.action_name self.assertSequenceEqual( queryset.order_by("id").values_list("id", flat=True), sorted(self._selected_values), @@ -145,21 +151,21 @@ def myhandler(sender, action, request, queryset, **kwargs): adminaction_end.connect(m3, sender=self.sender_model) self._run_action() - self.assertIn("adminaction_requested", handler_factory.invoked) - self.assertIn("adminaction_start", handler_factory.invoked) - self.assertIn("adminaction_end", handler_factory.invoked) + assert "adminaction_requested" in handler_factory.invoked + assert "adminaction_start" in handler_factory.invoked + assert "adminaction_end" in handler_factory.invoked finally: adminaction_requested.disconnect(m1, sender=self.sender_model) adminaction_start.disconnect(m2, sender=self.sender_model) adminaction_end.disconnect(m3, sender=self.sender_model) - def test_signal_requested(self): + def test_signal_requested(self) -> None: # test if adminaction_requested Signal can stop the action - def myhandler(sender, action, request, queryset, **kwargs): + def myhandler(sender, action, request, queryset, **kwargs) -> NoReturn: myhandler.invoked = True - self.assertEqual(action, self.action_name) + assert action == self.action_name self.assertSequenceEqual( queryset.order_by("id").values_list("id", flat=True), sorted(self._selected_values), @@ -171,17 +177,17 @@ def myhandler(sender, action, request, queryset, **kwargs): try: adminaction_requested.connect(myhandler, sender=self.sender_model) self._run_action(1) - self.assertTrue(myhandler.invoked) - self.assertIn(self.MESSAGE, self.app.cookies["messages"]) + assert myhandler.invoked + assert self.MESSAGE in self.app.cookies["messages"] finally: adminaction_requested.disconnect(myhandler, sender=self.sender_model) - def test_signal_start(self): + def test_signal_start(self) -> None: # test if adminaction_start Signal can stop the action - def myhandler(sender, action, request, queryset, **kwargs): + def myhandler(sender, action, request, queryset, **kwargs) -> NoReturn: myhandler.invoked = True - self.assertEqual(action, self.action_name) + assert action == self.action_name self.assertSequenceEqual( queryset.order_by("id").values_list("id", flat=True), sorted(self._selected_values), @@ -191,17 +197,17 @@ def myhandler(sender, action, request, queryset, **kwargs): try: adminaction_start.connect(myhandler, sender=self.sender_model) self._run_action(2) - self.assertTrue(myhandler.invoked) - self.assertIn(self.MESSAGE, self.app.cookies["messages"]) + assert myhandler.invoked + assert self.MESSAGE in self.app.cookies["messages"] finally: adminaction_start.disconnect(myhandler, sender=self.sender_model) - def test_signal_end(self): + def test_signal_end(self) -> None: # test if adminaction_start Signal can stop the action - def myhandler(sender, action, request, queryset, **kwargs): + def myhandler(sender, action, request, queryset, **kwargs) -> None: myhandler.invoked = True - self.assertEqual(action, self.action_name) + assert action == self.action_name self.assertSequenceEqual( queryset.order_by("id").values_list("id", flat=True), sorted(self._selected_values), @@ -211,7 +217,7 @@ def myhandler(sender, action, request, queryset, **kwargs): try: adminaction_end.connect(myhandler, sender=self.sender_model) self._run_action(2) - self.assertTrue(myhandler.invoked) + assert myhandler.invoked finally: adminaction_end.disconnect(myhandler, sender=self.sender_model) @@ -228,14 +234,12 @@ def ipaddress(not_valid=None): shuffle(class_a) first = class_a.pop() - return ".".join( - [ - str(first), - str(randrange(1, 256)), - str(randrange(1, 256)), - str(randrange(1, 256)), - ] - ) + return ".".join([ + str(first), + str(randrange(1, 256)), + str(randrange(1, 256)), + str(randrange(1, 256)), + ]) class DataFixtureClass(RandomDataFixture): # it can inherit of SequentialDataFixture, RandomDataFixture etc. @@ -278,16 +282,16 @@ class BaseTestCaseMixin: "adminactions.json", ] - def setUp(self): + def setUp(self) -> None: super().setUp() self.sett = self.settings(**SETTINGS) self.sett.enable() self.login() - def tearDown(self): + def tearDown(self) -> None: self.sett.disable() - def login(self, username="user_00", password="123"): + def login(self, username="user_00", password="123") -> None: user = User.objects.get(username=username) try: self.client.force_login(user) @@ -296,7 +300,7 @@ def login(self, username="user_00", password="123"): assert logged, "Unable login with credentials" self._user = authenticate(username=username, password=password) - def add_permission(self, *perms, **kwargs): + def add_permission(self, *perms, **kwargs) -> None: """add the right permission to the user""" target = kwargs.pop("user", self._user) if hasattr(target, "_perm_cache"): diff --git a/tox.ini b/tox.ini index ed0dd7fc..3c41b205 100644 --- a/tox.ini +++ b/tox.ini @@ -1,82 +1,42 @@ [tox] -# as per https://docs.djangoproject.com/en/1.11/faq/install/#what-python-version-can-i-use-with-django -envlist = d{32,42}-py{39,310,311} -; -;skip_missing_interpreters = true -; -[pytest] -;DJANGO_SETTINGS_MODULE = demo.settings -django_find_project = false -norecursedirs = demo .tox -addopts = - -v - --doctest-modules - --tb=short - --reuse-db - --cov=adminactions - --cov-report=html - --cov-config=tests/.coveragerc - --capture=no - --doctest-glob=adminactions/*.py - --echo-version django - -doctest_optionflags = -python_files = tests/test_*.py tests/**/test_*.py -markers = - functional: mark a test as functional - selenium: selenium test - skip: skip test +requires = + tox>=4.2 + tox-uv>=1.20.2 +env_list = + lint + docs + package + d{50, 42, 32}-py{313, 312, 311} [testenv] -passenv = - DISPLAY - CELERY_BROKER_URL - -setenv = - PYTHONDONTWRITEBYTECODE=true - CRYPTOGRAPHY_DONT_BUILD_RUST=1 - PYTHONPATH=./src:./tests - CELERY_ALWAYS_EAGER=1 - -whitelist_externals = mkdir - +description = run the tests with pytest +package = wheel +wheel_build_env = .pkg deps = - -rsrc/requirements/testing.pip - pypy: psycopg2cffi d32: django==3.2.* d42: django==4.2.* - -; only for local development - dev: git+https://github.com/django/django.git - - + d50: django==5.0.* + pypy: psycopg2cffi +pass_env = + CELERY_BROKER_URL + DISPLAY +set_env = + CELERY_ALWAYS_EAGER = 1 + CRYPTOGRAPHY_DONT_BUILD_RUST = 1 + DATABASE_URL = postgres://postgres:postgres@127.0.0.1:5432/adminactions + PYTHONDONTWRITEBYTECODE = true + PYTHONPATH = ./src:./tests commands = - {posargs:py.test tests/ src --doctest-modules --create-db} + {posargs:pytest tests/ src --doctest-modules --create-db} +dependency_groups = dev [testenv:lint] -envdir = {toxworkdir}/d32-py39/ +description = run static analysis and style check using flake8 skip_install = true deps = - black - flake8 - isort - pre-commit - -commands = - pre-commit run --all - -[testenv:package] -deps = - build - twine - -setenv = - TWINE_USERNAME = {env:TWINE_TEST_USERNAME:__token__} - TWINE_PASSWORD = {env:TWINE_TEST_PASSWORD} - + pre-commit-uv>=4.1.1 +pass_env = + HOMEPATH + PROGRAMDATA commands = - python -c "import shutil; shutil.rmtree('dist', ignore_errors=True)" - python -m build - python -m twine check dist/* - python -m twine upload --repository-url https://test.pypi.org/legacy/ dist/* - + pre-commit run --all-files --show-diff-on-failure diff --git a/uv.lock b/uv.lock new file mode 100644 index 00000000..e82a6716 --- /dev/null +++ b/uv.lock @@ -0,0 +1,1199 @@ +version = 1 +requires-python = ">=3.11.0" +resolution-markers = [ + "python_full_version >= '3.13'", + "python_full_version < '3.13'", +] + +[[package]] +name = "amqp" +version = "5.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "vine" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/79/fc/ec94a357dfc6683d8c86f8b4cfa5416a4c36b28052ec8260c77aca96a443/amqp-5.3.1.tar.gz", hash = "sha256:cddc00c725449522023bad949f70fff7b48f0b1ade74d170a6f10ab044739432", size = 129013 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/26/99/fc813cd978842c26c82534010ea849eee9ab3a13ea2b74e95cb9c99e747b/amqp-5.3.1-py3-none-any.whl", hash = "sha256:43b3319e1b4e7d1251833a93d672b4af1e40f3d632d479b98661a95f117880a2", size = 50944 }, +] + +[[package]] +name = "appdirs" +version = "1.4.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d7/d8/05696357e0311f5b5c316d7b95f46c669dd9c15aaeecbb48c7d0aeb88c40/appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41", size = 13470 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3b/00/2344469e2084fb287c2e0b57b72910309874c3245463acd6cf5e3db69324/appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128", size = 9566 }, +] + +[[package]] +name = "async-timeout" +version = "5.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a5/ae/136395dfbfe00dfc94da3f3e136d0b13f394cba8f4841120e34226265780/async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3", size = 9274 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fe/ba/e2081de779ca30d473f21f5b30e0e737c438205440784c7dfc81efc2b029/async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c", size = 6233 }, +] + +[[package]] +name = "attrs" +version = "25.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/49/7c/fdf464bcc51d23881d110abd74b512a42b3d5d376a55a831b44c603ae17f/attrs-25.1.0.tar.gz", hash = "sha256:1c97078a80c814273a76b2a298a932eb681c87415c11dee0a6921de7f1b02c3e", size = 810562 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fc/30/d4986a882011f9df997a55e6becd864812ccfcd821d64aac8570ee39f719/attrs-25.1.0-py3-none-any.whl", hash = "sha256:c75a69e28a550a7e93789579c22aa26b0f5b83b75dc4e08fe092980051e1090a", size = 63152 }, +] + +[[package]] +name = "beautifulsoup4" +version = "4.13.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "soupsieve" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f0/3c/adaf39ce1fb4afdd21b611e3d530b183bb7759c9b673d60db0e347fd4439/beautifulsoup4-4.13.3.tar.gz", hash = "sha256:1bd32405dacc920b42b83ba01644747ed77456a65760e285fbc47633ceddaf8b", size = 619516 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f9/49/6abb616eb3cbab6a7cca303dc02fdf3836de2e0b834bf966a7f5271a34d8/beautifulsoup4-4.13.3-py3-none-any.whl", hash = "sha256:99045d7d3f08f91f0d656bc9b7efbae189426cd913d830294a15eefa0ea4df16", size = 186015 }, +] + +[[package]] +name = "billiard" +version = "4.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7c/58/1546c970afcd2a2428b1bfafecf2371d8951cc34b46701bea73f4280989e/billiard-4.2.1.tar.gz", hash = "sha256:12b641b0c539073fc8d3f5b8b7be998956665c4233c7c1fcd66a7e677c4fb36f", size = 155031 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/30/da/43b15f28fe5f9e027b41c539abc5469052e9d48fd75f8ff094ba2a0ae767/billiard-4.2.1-py3-none-any.whl", hash = "sha256:40b59a4ac8806ba2c2369ea98d876bc6108b051c227baffd928c644d15d8f3cb", size = 86766 }, +] + +[[package]] +name = "black" +version = "25.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "mypy-extensions" }, + { name = "packaging" }, + { name = "pathspec" }, + { name = "platformdirs" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/94/49/26a7b0f3f35da4b5a65f081943b7bcd22d7002f5f0fb8098ec1ff21cb6ef/black-25.1.0.tar.gz", hash = "sha256:33496d5cd1222ad73391352b4ae8da15253c5de89b93a80b3e2c8d9a19ec2666", size = 649449 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/4f/87f596aca05c3ce5b94b8663dbfe242a12843caaa82dd3f85f1ffdc3f177/black-25.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a39337598244de4bae26475f77dda852ea00a93bd4c728e09eacd827ec929df0", size = 1614372 }, + { url = "https://files.pythonhosted.org/packages/e7/d0/2c34c36190b741c59c901e56ab7f6e54dad8df05a6272a9747ecef7c6036/black-25.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96c1c7cd856bba8e20094e36e0f948718dc688dba4a9d78c3adde52b9e6c2299", size = 1442865 }, + { url = "https://files.pythonhosted.org/packages/21/d4/7518c72262468430ead45cf22bd86c883a6448b9eb43672765d69a8f1248/black-25.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bce2e264d59c91e52d8000d507eb20a9aca4a778731a08cfff7e5ac4a4bb7096", size = 1749699 }, + { url = "https://files.pythonhosted.org/packages/58/db/4f5beb989b547f79096e035c4981ceb36ac2b552d0ac5f2620e941501c99/black-25.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:172b1dbff09f86ce6f4eb8edf9dede08b1fce58ba194c87d7a4f1a5aa2f5b3c2", size = 1428028 }, + { url = "https://files.pythonhosted.org/packages/83/71/3fe4741df7adf015ad8dfa082dd36c94ca86bb21f25608eb247b4afb15b2/black-25.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4b60580e829091e6f9238c848ea6750efed72140b91b048770b64e74fe04908b", size = 1650988 }, + { url = "https://files.pythonhosted.org/packages/13/f3/89aac8a83d73937ccd39bbe8fc6ac8860c11cfa0af5b1c96d081facac844/black-25.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e2978f6df243b155ef5fa7e558a43037c3079093ed5d10fd84c43900f2d8ecc", size = 1453985 }, + { url = "https://files.pythonhosted.org/packages/6f/22/b99efca33f1f3a1d2552c714b1e1b5ae92efac6c43e790ad539a163d1754/black-25.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b48735872ec535027d979e8dcb20bf4f70b5ac75a8ea99f127c106a7d7aba9f", size = 1783816 }, + { url = "https://files.pythonhosted.org/packages/18/7e/a27c3ad3822b6f2e0e00d63d58ff6299a99a5b3aee69fa77cd4b0076b261/black-25.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:ea0213189960bda9cf99be5b8c8ce66bb054af5e9e861249cd23471bd7b0b3ba", size = 1440860 }, + { url = "https://files.pythonhosted.org/packages/98/87/0edf98916640efa5d0696e1abb0a8357b52e69e82322628f25bf14d263d1/black-25.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f0b18a02996a836cc9c9c78e5babec10930862827b1b724ddfe98ccf2f2fe4f", size = 1650673 }, + { url = "https://files.pythonhosted.org/packages/52/e5/f7bf17207cf87fa6e9b676576749c6b6ed0d70f179a3d812c997870291c3/black-25.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:afebb7098bfbc70037a053b91ae8437c3857482d3a690fefc03e9ff7aa9a5fd3", size = 1453190 }, + { url = "https://files.pythonhosted.org/packages/e3/ee/adda3d46d4a9120772fae6de454c8495603c37c4c3b9c60f25b1ab6401fe/black-25.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:030b9759066a4ee5e5aca28c3c77f9c64789cdd4de8ac1df642c40b708be6171", size = 1782926 }, + { url = "https://files.pythonhosted.org/packages/cc/64/94eb5f45dcb997d2082f097a3944cfc7fe87e071907f677e80788a2d7b7a/black-25.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:a22f402b410566e2d1c950708c77ebf5ebd5d0d88a6a2e87c86d9fb48afa0d18", size = 1442613 }, + { url = "https://files.pythonhosted.org/packages/09/71/54e999902aed72baf26bca0d50781b01838251a462612966e9fc4891eadd/black-25.1.0-py3-none-any.whl", hash = "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717", size = 207646 }, +] + +[[package]] +name = "build" +version = "1.2.2.post1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "os_name == 'nt'" }, + { name = "packaging" }, + { name = "pyproject-hooks" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7d/46/aeab111f8e06793e4f0e421fcad593d547fb8313b50990f31681ee2fb1ad/build-1.2.2.post1.tar.gz", hash = "sha256:b36993e92ca9375a219c99e606a122ff365a760a2d4bba0caa09bd5278b608b7", size = 46701 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/c2/80633736cd183ee4a62107413def345f7e6e3c01563dbca1417363cf957e/build-1.2.2.post1-py3-none-any.whl", hash = "sha256:1d61c0887fa860c01971625baae8bdd338e517b836a2f70dd1f7aa3a6b2fc5b5", size = 22950 }, +] + +[[package]] +name = "cachetools" +version = "5.5.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d9/74/57df1ab0ce6bc5f6fa868e08de20df8ac58f9c44330c7671ad922d2bbeae/cachetools-5.5.1.tar.gz", hash = "sha256:70f238fbba50383ef62e55c6aff6d9673175fe59f7c6782c7a0b9e38f4a9df95", size = 28044 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/4e/de4ff18bcf55857ba18d3a4bd48c8a9fde6bb0980c9d20b263f05387fd88/cachetools-5.5.1-py3-none-any.whl", hash = "sha256:b76651fdc3b24ead3c648bbdeeb940c1b04d365b38b4af66788f9ec4a81d42bb", size = 9530 }, +] + +[[package]] +name = "celery" +version = "5.4.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "billiard" }, + { name = "click" }, + { name = "click-didyoumean" }, + { name = "click-plugins" }, + { name = "click-repl" }, + { name = "kombu" }, + { name = "python-dateutil" }, + { name = "tzdata" }, + { name = "vine" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8a/9c/cf0bce2cc1c8971bf56629d8f180e4ca35612c7e79e6e432e785261a8be4/celery-5.4.0.tar.gz", hash = "sha256:504a19140e8d3029d5acad88330c541d4c3f64c789d85f94756762d8bca7e706", size = 1575692 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/90/c4/6a4d3772e5407622feb93dd25c86ce3c0fee746fa822a777a627d56b4f2a/celery-5.4.0-py3-none-any.whl", hash = "sha256:369631eb580cf8c51a82721ec538684994f8277637edde2dfc0dacd73ed97f64", size = 425983 }, +] + +[[package]] +name = "certifi" +version = "2025.1.31" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1c/ab/c9f1e32b7b1bf505bf26f0ef697775960db7932abeb7b516de930ba2705f/certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651", size = 167577 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/fc/bce832fd4fd99766c04d1ee0eead6b0ec6486fb100ae5e74c1d91292b982/certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe", size = 166393 }, +] + +[[package]] +name = "cffi" +version = "1.17.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycparser" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/34/33/e1b8a1ba29025adbdcda5fb3a36f94c03d771c1b7b12f726ff7fef2ebe36/cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655", size = 171727 }, + { url = "https://files.pythonhosted.org/packages/3d/97/50228be003bb2802627d28ec0627837ac0bf35c90cf769812056f235b2d1/cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0", size = 181400 }, + { url = "https://files.pythonhosted.org/packages/86/c5/28b2d6f799ec0bdecf44dced2ec5ed43e0eb63097b0f58c293583b406582/cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", size = 172448 }, + { url = "https://files.pythonhosted.org/packages/50/b9/db34c4755a7bd1cb2d1603ac3863f22bcecbd1ba29e5ee841a4bc510b294/cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", size = 181976 }, + { url = "https://files.pythonhosted.org/packages/bf/ee/f94057fa6426481d663b88637a9a10e859e492c73d0384514a17d78ee205/cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", size = 172475 }, + { url = "https://files.pythonhosted.org/packages/7c/fc/6a8cb64e5f0324877d503c854da15d76c1e50eb722e320b15345c4d0c6de/cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", size = 182009 }, +] + +[[package]] +name = "chardet" +version = "5.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/0d/f7b6ab21ec75897ed80c17d79b15951a719226b9fababf1e40ea74d69079/chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7", size = 2069618 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/6f/f5fbc992a329ee4e0f288c1fe0e2ad9485ed064cac731ed2fe47dcc38cbf/chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970", size = 199385 }, +] + +[[package]] +name = "check-manifest" +version = "0.50" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "build" }, + { name = "setuptools" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a8/ab/7607952f2c8d34c4124309dd3ea17c256fd3420a4ade01322daf9402b0b5/check_manifest-0.50.tar.gz", hash = "sha256:d300f9f292986aa1a30424af44eb45c5644e0a810e392e62d553b24bb3393494", size = 44827 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/55/92207fa9b92ac2ade5593b1280f804f2590a680b7fe96775eb26074eec6b/check_manifest-0.50-py3-none-any.whl", hash = "sha256:6ab3e3aa72a008da3314b432f4c768c9647b4d6d8032f9e1a4672a572118e48c", size = 20385 }, +] + +[[package]] +name = "click" +version = "8.1.8" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188 }, +] + +[[package]] +name = "click-didyoumean" +version = "0.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/30/ce/217289b77c590ea1e7c24242d9ddd6e249e52c795ff10fac2c50062c48cb/click_didyoumean-0.3.1.tar.gz", hash = "sha256:4f82fdff0dbe64ef8ab2279bd6aa3f6a99c3b28c05aa09cbfc07c9d7fbb5a463", size = 3089 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1b/5b/974430b5ffdb7a4f1941d13d83c64a0395114503cc357c6b9ae4ce5047ed/click_didyoumean-0.3.1-py3-none-any.whl", hash = "sha256:5c4bb6007cfea5f2fd6583a2fb6701a22a41eb98957e63d0fac41c10e7c3117c", size = 3631 }, +] + +[[package]] +name = "click-plugins" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5f/1d/45434f64ed749540af821fd7e42b8e4d23ac04b1eda7c26613288d6cd8a8/click-plugins-1.1.1.tar.gz", hash = "sha256:46ab999744a9d831159c3411bb0c79346d94a444df9a3a3742e9ed63645f264b", size = 8164 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/da/824b92d9942f4e472702488857914bdd50f73021efea15b4cad9aca8ecef/click_plugins-1.1.1-py2.py3-none-any.whl", hash = "sha256:5d262006d3222f5057fd81e1623d4443e41dcda5dc815c06b442aa3c02889fc8", size = 7497 }, +] + +[[package]] +name = "click-repl" +version = "0.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "prompt-toolkit" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cb/a2/57f4ac79838cfae6912f997b4d1a64a858fb0c86d7fcaae6f7b58d267fca/click-repl-0.3.0.tar.gz", hash = "sha256:17849c23dba3d667247dc4defe1757fff98694e90fe37474f3feebb69ced26a9", size = 10449 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/52/40/9d857001228658f0d59e97ebd4c346fe73e138c6de1bce61dc568a57c7f8/click_repl-0.3.0-py3-none-any.whl", hash = "sha256:fb7e06deb8da8de86180a33a9da97ac316751c094c6899382da7feeeeb51b812", size = 10289 }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, +] + +[[package]] +name = "coverage" +version = "7.6.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/84/ba/ac14d281f80aab516275012e8875991bb06203957aa1e19950139238d658/coverage-7.6.10.tar.gz", hash = "sha256:7fb105327c8f8f0682e29843e2ff96af9dcbe5bab8eeb4b398c6a33a16d80a23", size = 803868 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/85/d2/5e175fcf6766cf7501a8541d81778fd2f52f4870100e791f5327fd23270b/coverage-7.6.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ea3c8f04b3e4af80e17bab607c386a830ffc2fb88a5484e1df756478cf70d1d3", size = 208088 }, + { url = "https://files.pythonhosted.org/packages/4b/6f/06db4dc8fca33c13b673986e20e466fd936235a6ec1f0045c3853ac1b593/coverage-7.6.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:507a20fc863cae1d5720797761b42d2d87a04b3e5aeb682ef3b7332e90598f43", size = 208536 }, + { url = "https://files.pythonhosted.org/packages/0d/62/c6a0cf80318c1c1af376d52df444da3608eafc913b82c84a4600d8349472/coverage-7.6.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d37a84878285b903c0fe21ac8794c6dab58150e9359f1aaebbeddd6412d53132", size = 240474 }, + { url = "https://files.pythonhosted.org/packages/a3/59/750adafc2e57786d2e8739a46b680d4fb0fbc2d57fbcb161290a9f1ecf23/coverage-7.6.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a534738b47b0de1995f85f582d983d94031dffb48ab86c95bdf88dc62212142f", size = 237880 }, + { url = "https://files.pythonhosted.org/packages/2c/f8/ef009b3b98e9f7033c19deb40d629354aab1d8b2d7f9cfec284dbedf5096/coverage-7.6.10-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d7a2bf79378d8fb8afaa994f91bfd8215134f8631d27eba3e0e2c13546ce994", size = 239750 }, + { url = "https://files.pythonhosted.org/packages/a6/e2/6622f3b70f5f5b59f705e680dae6db64421af05a5d1e389afd24dae62e5b/coverage-7.6.10-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6713ba4b4ebc330f3def51df1d5d38fad60b66720948112f114968feb52d3f99", size = 238642 }, + { url = "https://files.pythonhosted.org/packages/2d/10/57ac3f191a3c95c67844099514ff44e6e19b2915cd1c22269fb27f9b17b6/coverage-7.6.10-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ab32947f481f7e8c763fa2c92fd9f44eeb143e7610c4ca9ecd6a36adab4081bd", size = 237266 }, + { url = "https://files.pythonhosted.org/packages/ee/2d/7016f4ad9d553cabcb7333ed78ff9d27248ec4eba8dd21fa488254dff894/coverage-7.6.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7bbd8c8f1b115b892e34ba66a097b915d3871db7ce0e6b9901f462ff3a975377", size = 238045 }, + { url = "https://files.pythonhosted.org/packages/a7/fe/45af5c82389a71e0cae4546413266d2195c3744849669b0bab4b5f2c75da/coverage-7.6.10-cp311-cp311-win32.whl", hash = "sha256:299e91b274c5c9cdb64cbdf1b3e4a8fe538a7a86acdd08fae52301b28ba297f8", size = 210647 }, + { url = "https://files.pythonhosted.org/packages/db/11/3f8e803a43b79bc534c6a506674da9d614e990e37118b4506faf70d46ed6/coverage-7.6.10-cp311-cp311-win_amd64.whl", hash = "sha256:489a01f94aa581dbd961f306e37d75d4ba16104bbfa2b0edb21d29b73be83609", size = 211508 }, + { url = "https://files.pythonhosted.org/packages/86/77/19d09ea06f92fdf0487499283b1b7af06bc422ea94534c8fe3a4cd023641/coverage-7.6.10-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:27c6e64726b307782fa5cbe531e7647aee385a29b2107cd87ba7c0105a5d3853", size = 208281 }, + { url = "https://files.pythonhosted.org/packages/b6/67/5479b9f2f99fcfb49c0d5cf61912a5255ef80b6e80a3cddba39c38146cf4/coverage-7.6.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c56e097019e72c373bae32d946ecf9858fda841e48d82df7e81c63ac25554078", size = 208514 }, + { url = "https://files.pythonhosted.org/packages/15/d1/febf59030ce1c83b7331c3546d7317e5120c5966471727aa7ac157729c4b/coverage-7.6.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7827a5bc7bdb197b9e066cdf650b2887597ad124dd99777332776f7b7c7d0d0", size = 241537 }, + { url = "https://files.pythonhosted.org/packages/4b/7e/5ac4c90192130e7cf8b63153fe620c8bfd9068f89a6d9b5f26f1550f7a26/coverage-7.6.10-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:204a8238afe787323a8b47d8be4df89772d5c1e4651b9ffa808552bdf20e1d50", size = 238572 }, + { url = "https://files.pythonhosted.org/packages/dc/03/0334a79b26ecf59958f2fe9dd1f5ab3e2f88db876f5071933de39af09647/coverage-7.6.10-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e67926f51821b8e9deb6426ff3164870976fe414d033ad90ea75e7ed0c2e5022", size = 240639 }, + { url = "https://files.pythonhosted.org/packages/d7/45/8a707f23c202208d7b286d78ad6233f50dcf929319b664b6cc18a03c1aae/coverage-7.6.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e78b270eadb5702938c3dbe9367f878249b5ef9a2fcc5360ac7bff694310d17b", size = 240072 }, + { url = "https://files.pythonhosted.org/packages/66/02/603ce0ac2d02bc7b393279ef618940b4a0535b0868ee791140bda9ecfa40/coverage-7.6.10-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:714f942b9c15c3a7a5fe6876ce30af831c2ad4ce902410b7466b662358c852c0", size = 238386 }, + { url = "https://files.pythonhosted.org/packages/04/62/4e6887e9be060f5d18f1dd58c2838b2d9646faf353232dec4e2d4b1c8644/coverage-7.6.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:abb02e2f5a3187b2ac4cd46b8ced85a0858230b577ccb2c62c81482ca7d18852", size = 240054 }, + { url = "https://files.pythonhosted.org/packages/5c/74/83ae4151c170d8bd071924f212add22a0e62a7fe2b149edf016aeecad17c/coverage-7.6.10-cp312-cp312-win32.whl", hash = "sha256:55b201b97286cf61f5e76063f9e2a1d8d2972fc2fcfd2c1272530172fd28c359", size = 210904 }, + { url = "https://files.pythonhosted.org/packages/c3/54/de0893186a221478f5880283119fc40483bc460b27c4c71d1b8bba3474b9/coverage-7.6.10-cp312-cp312-win_amd64.whl", hash = "sha256:e4ae5ac5e0d1e4edfc9b4b57b4cbecd5bc266a6915c500f358817a8496739247", size = 211692 }, + { url = "https://files.pythonhosted.org/packages/25/6d/31883d78865529257bf847df5789e2ae80e99de8a460c3453dbfbe0db069/coverage-7.6.10-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:05fca8ba6a87aabdd2d30d0b6c838b50510b56cdcfc604d40760dae7153b73d9", size = 208308 }, + { url = "https://files.pythonhosted.org/packages/70/22/3f2b129cc08de00c83b0ad6252e034320946abfc3e4235c009e57cfeee05/coverage-7.6.10-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9e80eba8801c386f72e0712a0453431259c45c3249f0009aff537a517b52942b", size = 208565 }, + { url = "https://files.pythonhosted.org/packages/97/0a/d89bc2d1cc61d3a8dfe9e9d75217b2be85f6c73ebf1b9e3c2f4e797f4531/coverage-7.6.10-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a372c89c939d57abe09e08c0578c1d212e7a678135d53aa16eec4430adc5e690", size = 241083 }, + { url = "https://files.pythonhosted.org/packages/4c/81/6d64b88a00c7a7aaed3a657b8eaa0931f37a6395fcef61e53ff742b49c97/coverage-7.6.10-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ec22b5e7fe7a0fa8509181c4aac1db48f3dd4d3a566131b313d1efc102892c18", size = 238235 }, + { url = "https://files.pythonhosted.org/packages/9a/0b/7797d4193f5adb4b837207ed87fecf5fc38f7cc612b369a8e8e12d9fa114/coverage-7.6.10-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26bcf5c4df41cad1b19c84af71c22cbc9ea9a547fc973f1f2cc9a290002c8b3c", size = 240220 }, + { url = "https://files.pythonhosted.org/packages/65/4d/6f83ca1bddcf8e51bf8ff71572f39a1c73c34cf50e752a952c34f24d0a60/coverage-7.6.10-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4e4630c26b6084c9b3cb53b15bd488f30ceb50b73c35c5ad7871b869cb7365fd", size = 239847 }, + { url = "https://files.pythonhosted.org/packages/30/9d/2470df6aa146aff4c65fee0f87f58d2164a67533c771c9cc12ffcdb865d5/coverage-7.6.10-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2396e8116db77789f819d2bc8a7e200232b7a282c66e0ae2d2cd84581a89757e", size = 237922 }, + { url = "https://files.pythonhosted.org/packages/08/dd/723fef5d901e6a89f2507094db66c091449c8ba03272861eaefa773ad95c/coverage-7.6.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:79109c70cc0882e4d2d002fe69a24aa504dec0cc17169b3c7f41a1d341a73694", size = 239783 }, + { url = "https://files.pythonhosted.org/packages/3d/f7/64d3298b2baf261cb35466000628706ce20a82d42faf9b771af447cd2b76/coverage-7.6.10-cp313-cp313-win32.whl", hash = "sha256:9e1747bab246d6ff2c4f28b4d186b205adced9f7bd9dc362051cc37c4a0c7bd6", size = 210965 }, + { url = "https://files.pythonhosted.org/packages/d5/58/ec43499a7fc681212fe7742fe90b2bc361cdb72e3181ace1604247a5b24d/coverage-7.6.10-cp313-cp313-win_amd64.whl", hash = "sha256:254f1a3b1eef5f7ed23ef265eaa89c65c8c5b6b257327c149db1ca9d4a35f25e", size = 211719 }, + { url = "https://files.pythonhosted.org/packages/ab/c9/f2857a135bcff4330c1e90e7d03446b036b2363d4ad37eb5e3a47bbac8a6/coverage-7.6.10-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2ccf240eb719789cedbb9fd1338055de2761088202a9a0b73032857e53f612fe", size = 209050 }, + { url = "https://files.pythonhosted.org/packages/aa/b3/f840e5bd777d8433caa9e4a1eb20503495709f697341ac1a8ee6a3c906ad/coverage-7.6.10-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:0c807ca74d5a5e64427c8805de15b9ca140bba13572d6d74e262f46f50b13273", size = 209321 }, + { url = "https://files.pythonhosted.org/packages/85/7d/125a5362180fcc1c03d91850fc020f3831d5cda09319522bcfa6b2b70be7/coverage-7.6.10-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bcfa46d7709b5a7ffe089075799b902020b62e7ee56ebaed2f4bdac04c508d8", size = 252039 }, + { url = "https://files.pythonhosted.org/packages/a9/9c/4358bf3c74baf1f9bddd2baf3756b54c07f2cfd2535f0a47f1e7757e54b3/coverage-7.6.10-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4e0de1e902669dccbf80b0415fb6b43d27edca2fbd48c74da378923b05316098", size = 247758 }, + { url = "https://files.pythonhosted.org/packages/cf/c7/de3eb6fc5263b26fab5cda3de7a0f80e317597a4bad4781859f72885f300/coverage-7.6.10-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f7b444c42bbc533aaae6b5a2166fd1a797cdb5eb58ee51a92bee1eb94a1e1cb", size = 250119 }, + { url = "https://files.pythonhosted.org/packages/3e/e6/43de91f8ba2ec9140c6a4af1102141712949903dc732cf739167cfa7a3bc/coverage-7.6.10-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b330368cb99ef72fcd2dc3ed260adf67b31499584dc8a20225e85bfe6f6cfed0", size = 249597 }, + { url = "https://files.pythonhosted.org/packages/08/40/61158b5499aa2adf9e37bc6d0117e8f6788625b283d51e7e0c53cf340530/coverage-7.6.10-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:9a7cfb50515f87f7ed30bc882f68812fd98bc2852957df69f3003d22a2aa0abf", size = 247473 }, + { url = "https://files.pythonhosted.org/packages/50/69/b3f2416725621e9f112e74e8470793d5b5995f146f596f133678a633b77e/coverage-7.6.10-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6f93531882a5f68c28090f901b1d135de61b56331bba82028489bc51bdd818d2", size = 248737 }, + { url = "https://files.pythonhosted.org/packages/3c/6e/fe899fb937657db6df31cc3e61c6968cb56d36d7326361847440a430152e/coverage-7.6.10-cp313-cp313t-win32.whl", hash = "sha256:89d76815a26197c858f53c7f6a656686ec392b25991f9e409bcef020cd532312", size = 211611 }, + { url = "https://files.pythonhosted.org/packages/1c/55/52f5e66142a9d7bc93a15192eba7a78513d2abf6b3558d77b4ca32f5f424/coverage-7.6.10-cp313-cp313t-win_amd64.whl", hash = "sha256:54a5f0f43950a36312155dae55c505a76cd7f2b12d26abeebbe7a0b36dbc868d", size = 212781 }, +] + +[package.optional-dependencies] +toml = [ + { name = "tomli", marker = "python_full_version <= '3.11'" }, +] + +[[package]] +name = "distlib" +version = "0.3.9" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0d/dd/1bec4c5ddb504ca60fc29472f3d27e8d4da1257a854e1d96742f15c1d02d/distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403", size = 613923 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/91/a1/cf2472db20f7ce4a6be1253a81cfdf85ad9c7885ffbed7047fb72c24cf87/distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87", size = 468973 }, +] + +[[package]] +name = "django-admin-extra-urls" +version = "4.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ee/25/4afe0b88b91b49611437f4ae5d37b9ea4e907728a730e6b8e2ef970db4eb/django-admin-extra-urls-4.1.1.tar.gz", hash = "sha256:b896eebc24779081f5bb5015c41fb12a741c61d520eec88688749e4991f7cbf5", size = 108613 } + +[[package]] +name = "django-adminactions" +version = "2.3.0" +source = { editable = "." } +dependencies = [ + { name = "pytz" }, + { name = "xlrd" }, + { name = "xlwt" }, +] + +[package.dev-dependencies] +dev = [ + { name = "black" }, + { name = "celery" }, + { name = "check-manifest" }, + { name = "django-admin-extra-urls" }, + { name = "django-dynamic-fixture" }, + { name = "django-environ" }, + { name = "django-webtest" }, + { name = "mock" }, + { name = "modernize" }, + { name = "mypy" }, + { name = "pillow" }, + { name = "psycopg2" }, + { name = "pytest" }, + { name = "pytest-cache" }, + { name = "pytest-cov" }, + { name = "pytest-django" }, + { name = "pytest-echo" }, + { name = "readme" }, + { name = "redis" }, + { name = "ruff" }, + { name = "selenium" }, + { name = "setuptools" }, + { name = "tox" }, +] + +[package.metadata] +requires-dist = [ + { name = "pytz" }, + { name = "xlrd", specifier = ">=0.9.2" }, + { name = "xlwt" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "black", specifier = ">=25.1" }, + { name = "celery", specifier = ">=5.4" }, + { name = "check-manifest", specifier = ">=0.50" }, + { name = "django-admin-extra-urls", specifier = ">=4.1.1" }, + { name = "django-dynamic-fixture", specifier = ">=4.0.1" }, + { name = "django-environ", specifier = ">=0.12" }, + { name = "django-webtest", specifier = ">1.9.6" }, + { name = "mock", specifier = ">=1.0.1" }, + { name = "modernize", specifier = ">=0.8" }, + { name = "mypy", specifier = ">=1.15" }, + { name = "pillow", specifier = ">=11.1" }, + { name = "psycopg2", specifier = ">=2.9.10" }, + { name = "pytest", specifier = ">=8.3.4" }, + { name = "pytest-cache", specifier = ">=1" }, + { name = "pytest-cov", specifier = ">=6" }, + { name = "pytest-django", specifier = ">=4.9" }, + { name = "pytest-echo", specifier = ">=1.8.1" }, + { name = "readme", specifier = ">=0.7.1" }, + { name = "redis", specifier = ">=5.2.1" }, + { name = "ruff", specifier = ">=0.9.4" }, + { name = "selenium", specifier = ">=2.42" }, + { name = "setuptools", specifier = ">=15" }, + { name = "tox", specifier = ">=4.2" }, +] + +[[package]] +name = "django-dynamic-fixture" +version = "4.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/47/62/d7ca06aece37b7c651b7ffe1aff15e89dfc18653e266af203c5ae9d5212b/django-dynamic-fixture-4.0.1.tar.gz", hash = "sha256:2a2197578b7702db8f5eed9ad704f6be33bac8bf0111c7c92f6063c2a4d02933", size = 44278 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5f/ca/f77782903f93a4ba42204dce89682c5de734d88002cefa6071f805697620/django_dynamic_fixture-4.0.1-py3-none-any.whl", hash = "sha256:d0611b6dc594fb1bccad1fd94dade89cc8deca12385bc2763baded3e48322547", size = 58712 }, +] + +[[package]] +name = "django-environ" +version = "0.12.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/04/65d2521842c42f4716225f20d8443a50804920606aec018188bbee30a6b0/django_environ-0.12.0.tar.gz", hash = "sha256:227dc891453dd5bde769c3449cf4a74b6f2ee8f7ab2361c93a07068f4179041a", size = 56804 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/b3/0a3bec4ecbfee960f39b1842c2f91e4754251e0a6ed443db9fe3f666ba8f/django_environ-0.12.0-py2.py3-none-any.whl", hash = "sha256:92fb346a158abda07ffe6eb23135ce92843af06ecf8753f43adf9d2366dcc0ca", size = 19957 }, +] + +[[package]] +name = "django-webtest" +version = "1.9.12" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "webtest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/47/e3/e087630e62bcf29ed1c3560ae98b12c45e0ac07b4899ab3b8ef6a1967dde/django_webtest-1.9.12.tar.gz", hash = "sha256:5012c30665e7a6e585a1544eda75045d07d5b3f5ccccd4d0fe144c4555884095", size = 28848 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/97/0b/c7e6c3a59ea001ca51a966477eafd2746e63b6ff2fce7dcf3c3b3c0ad765/django_webtest-1.9.12-py3-none-any.whl", hash = "sha256:de5c988c20eef7abbb3d0508494d9e576af08087d0fb6109b1d54f15ef4d78fa", size = 16583 }, +] + +[[package]] +name = "docutils" +version = "0.21.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ae/ed/aefcc8cd0ba62a0560c3c18c33925362d46c6075480bfa4df87b28e169a9/docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f", size = 2204444 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2", size = 587408 }, +] + +[[package]] +name = "execnet" +version = "2.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bb/ff/b4c0dc78fbe20c3e59c0c7334de0c27eb4001a2b2017999af398bf730817/execnet-2.1.1.tar.gz", hash = "sha256:5189b52c6121c24feae288166ab41b32549c7e2348652736540b9e6e7d4e72e3", size = 166524 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/43/09/2aea36ff60d16dd8879bdb2f5b3ee0ba8d08cbbdcdfe870e695ce3784385/execnet-2.1.1-py3-none-any.whl", hash = "sha256:26dee51f1b80cebd6d0ca8e74dd8745419761d3bef34163928cbebbdc4749fdc", size = 40612 }, +] + +[[package]] +name = "filelock" +version = "3.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/dc/9c/0b15fb47b464e1b663b1acd1253a062aa5feecb07d4e597daea542ebd2b5/filelock-3.17.0.tar.gz", hash = "sha256:ee4e77401ef576ebb38cd7f13b9b28893194acc20a8e68e18730ba9c0e54660e", size = 18027 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/89/ec/00d68c4ddfedfe64159999e5f8a98fb8442729a63e2077eb9dcd89623d27/filelock-3.17.0-py3-none-any.whl", hash = "sha256:533dc2f7ba78dc2f0f531fc6c4940addf7b70a481e269a5a3b93be94ffbe8338", size = 16164 }, +] + +[[package]] +name = "fissix" +version = "24.4.24" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "appdirs" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/11/fb/174b49419d4f4d057e65cecba8107a8074a67a3aea59bc80f4e50875b479/fissix-24.4.24.tar.gz", hash = "sha256:7e8f1e448d1ebc1c8be68be8bf71123650710076ea9dcecb7801804b04f43547", size = 160270 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b4/c9/7d293a9ea42ef05d6260714f8cf641ba64fab438be55312b1c719d4e7cc6/fissix-24.4.24-py3-none-any.whl", hash = "sha256:be7f5c66e9e212bd9b3365c9e8f2453e973d0a645f31c8eba842724adb4c0c50", size = 188533 }, +] + +[[package]] +name = "h11" +version = "0.14.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f5/38/3af3d3633a34a3316095b39c8e8fb4853a28a536e55d347bd8d8e9a14b03/h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", size = 100418 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/95/04/ff642e65ad6b90db43e668d70ffb6736436c7ce41fcc549f4e9472234127/h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761", size = 58259 }, +] + +[[package]] +name = "idna" +version = "3.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 }, +] + +[[package]] +name = "iniconfig" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", size = 4646 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892 }, +] + +[[package]] +name = "kombu" +version = "5.4.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "amqp" }, + { name = "tzdata" }, + { name = "vine" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/38/4d/b93fcb353d279839cc35d0012bee805ed0cf61c07587916bfc35dbfddaf1/kombu-5.4.2.tar.gz", hash = "sha256:eef572dd2fd9fc614b37580e3caeafdd5af46c1eff31e7fba89138cdb406f2cf", size = 442858 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/87/ec/7811a3cf9fdfee3ee88e54d08fcbc3fabe7c1b6e4059826c59d7b795651c/kombu-5.4.2-py3-none-any.whl", hash = "sha256:14212f5ccf022fc0a70453bb025a1dcc32782a588c49ea866884047d66e14763", size = 201349 }, +] + +[[package]] +name = "legacy-cgi" +version = "2.6.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ad/2e/e1860989bc6cfdecba66db37f2f783636b97a1248ac25fbe864b6e931c22/legacy_cgi-2.6.2.tar.gz", hash = "sha256:9952471ceb304043b104c22d00b4f333cac27a6abe446d8a528fc437cf13c85f", size = 24794 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4c/cd/54d1fd92d7f6aca9523d8583052e00b273bdfe28aa7fd54a3a5759dab05e/legacy_cgi-2.6.2-py3-none-any.whl", hash = "sha256:a7b83afb1baf6ebeb56522537c5943ef9813cf933f6715e88a803f7edbce0bff", size = 19572 }, +] + +[[package]] +name = "mock" +version = "5.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/66/ab/41d09a46985ead5839d8be987acda54b5bb93f713b3969cc0be4f81c455b/mock-5.1.0.tar.gz", hash = "sha256:5e96aad5ccda4718e0a229ed94b2024df75cc2d55575ba5762d31f5767b8767d", size = 80232 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6b/20/471f41173930550f279ccb65596a5ac19b9ac974a8d93679bcd3e0c31498/mock-5.1.0-py3-none-any.whl", hash = "sha256:18c694e5ae8a208cdb3d2c20a993ca1a7b0efa258c247a1e565150f477f83744", size = 30938 }, +] + +[[package]] +name = "modernize" +version = "0.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "fissix" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e5/97/b7bb97eda53d8784b01dee37aa84dbb2212d89a465a913cd53284568c921/modernize-0.8.0.tar.gz", hash = "sha256:1672b4bb19a060a53dd0518cc8f70fc83591c7246e532223459f85d338c60f55", size = 21304 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/73/6d/c381a4b811a3c529626268276512d1b5abef601e45bc04f0e797284b49bc/modernize-0.8.0-py2.py3-none-any.whl", hash = "sha256:b51f930ac9d726903f2c7f9038146d6061a14509140d6e4498827b19b5610120", size = 27243 }, +] + +[[package]] +name = "mypy" +version = "1.15.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mypy-extensions" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ce/43/d5e49a86afa64bd3839ea0d5b9c7103487007d728e1293f52525d6d5486a/mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43", size = 3239717 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/03/bc/f6339726c627bd7ca1ce0fa56c9ae2d0144604a319e0e339bdadafbbb599/mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f", size = 10662338 }, + { url = "https://files.pythonhosted.org/packages/e2/90/8dcf506ca1a09b0d17555cc00cd69aee402c203911410136cd716559efe7/mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5", size = 9787540 }, + { url = "https://files.pythonhosted.org/packages/05/05/a10f9479681e5da09ef2f9426f650d7b550d4bafbef683b69aad1ba87457/mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e", size = 11538051 }, + { url = "https://files.pythonhosted.org/packages/e9/9a/1f7d18b30edd57441a6411fcbc0c6869448d1a4bacbaee60656ac0fc29c8/mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c", size = 12286751 }, + { url = "https://files.pythonhosted.org/packages/72/af/19ff499b6f1dafcaf56f9881f7a965ac2f474f69f6f618b5175b044299f5/mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f", size = 12421783 }, + { url = "https://files.pythonhosted.org/packages/96/39/11b57431a1f686c1aed54bf794870efe0f6aeca11aca281a0bd87a5ad42c/mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f", size = 9265618 }, + { url = "https://files.pythonhosted.org/packages/98/3a/03c74331c5eb8bd025734e04c9840532226775c47a2c39b56a0c8d4f128d/mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd", size = 10793981 }, + { url = "https://files.pythonhosted.org/packages/f0/1a/41759b18f2cfd568848a37c89030aeb03534411eef981df621d8fad08a1d/mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f", size = 9749175 }, + { url = "https://files.pythonhosted.org/packages/12/7e/873481abf1ef112c582db832740f4c11b2bfa510e829d6da29b0ab8c3f9c/mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464", size = 11455675 }, + { url = "https://files.pythonhosted.org/packages/b3/d0/92ae4cde706923a2d3f2d6c39629134063ff64b9dedca9c1388363da072d/mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee", size = 12410020 }, + { url = "https://files.pythonhosted.org/packages/46/8b/df49974b337cce35f828ba6fda228152d6db45fed4c86ba56ffe442434fd/mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e", size = 12498582 }, + { url = "https://files.pythonhosted.org/packages/13/50/da5203fcf6c53044a0b699939f31075c45ae8a4cadf538a9069b165c1050/mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22", size = 9366614 }, + { url = "https://files.pythonhosted.org/packages/6a/9b/fd2e05d6ffff24d912f150b87db9e364fa8282045c875654ce7e32fffa66/mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445", size = 10788592 }, + { url = "https://files.pythonhosted.org/packages/74/37/b246d711c28a03ead1fd906bbc7106659aed7c089d55fe40dd58db812628/mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d", size = 9753611 }, + { url = "https://files.pythonhosted.org/packages/a6/ac/395808a92e10cfdac8003c3de9a2ab6dc7cde6c0d2a4df3df1b815ffd067/mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5", size = 11438443 }, + { url = "https://files.pythonhosted.org/packages/d2/8b/801aa06445d2de3895f59e476f38f3f8d610ef5d6908245f07d002676cbf/mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036", size = 12402541 }, + { url = "https://files.pythonhosted.org/packages/c7/67/5a4268782eb77344cc613a4cf23540928e41f018a9a1ec4c6882baf20ab8/mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357", size = 12494348 }, + { url = "https://files.pythonhosted.org/packages/83/3e/57bb447f7bbbfaabf1712d96f9df142624a386d98fb026a761532526057e/mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf", size = 9373648 }, + { url = "https://files.pythonhosted.org/packages/09/4e/a7d65c7322c510de2c409ff3828b03354a7c43f5a8ed458a7a131b41c7b9/mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e", size = 2221777 }, +] + +[[package]] +name = "mypy-extensions" +version = "1.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/98/a4/1ab47638b92648243faf97a5aeb6ea83059cc3624972ab6b8d2316078d3f/mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782", size = 4433 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/e2/5d3f6ada4297caebe1a2add3b126fe800c96f56dbe5d1988a2cbe0b267aa/mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", size = 4695 }, +] + +[[package]] +name = "nh3" +version = "0.2.20" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/46/f2/eb781d94c7855e9129cbbdd3ab09a470441e4176a82a396ae1df270a7333/nh3-0.2.20.tar.gz", hash = "sha256:9705c42d7ff88a0bea546c82d7fe5e59135e3d3f057e485394f491248a1f8ed5", size = 17489 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/65/d31d93b6d1e5fe80d0cc18f0b96eaa561edfa0a15a6ef6b0fce50202a931/nh3-0.2.20-cp313-cp313t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:e1061a4ab6681f6bdf72b110eea0c4e1379d57c9de937db3be4202f7ad6043db", size = 1202187 }, + { url = "https://files.pythonhosted.org/packages/b4/ae/5b03bf198e06921454012e4b9a51e676d26fd37d9fdc1f29371a0b380487/nh3-0.2.20-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb4254b1dac4a1ee49919a5b3f1caf9803ea8dada1816d9e8289e63d3cd0dd9a", size = 737822 }, + { url = "https://files.pythonhosted.org/packages/0a/53/a12dffb6ee3772deba82eb5997667fc835afd2e813d1f4080d8738f29eec/nh3-0.2.20-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0ae9cbd713524cdb81e64663d0d6aae26f678db9f2cd9db0bf162606f1f9f20c", size = 756643 }, + { url = "https://files.pythonhosted.org/packages/d0/0c/6cd2c5ac3e6e31f2a28721e8e2a924cb6b05ad054bf787bd1816ffd40b96/nh3-0.2.20-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e1f7370b4e14cc03f5ae141ef30a1caf81fa5787711f80be9081418dd9eb79d2", size = 923415 }, + { url = "https://files.pythonhosted.org/packages/64/f0/229a6c8b81b86ba22d8e7f27ade62cb2fcfb987e570f49944fdd8490a76a/nh3-0.2.20-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:ac4d27dc836a476efffc6eb661994426b8b805c951b29c9cf2ff36bc9ad58bc5", size = 994959 }, + { url = "https://files.pythonhosted.org/packages/75/e3/62ae3d3b658739ee15b129356fe6d4c4bc8ab235d7bf2e0d2794d64f7bc6/nh3-0.2.20-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:4fd2e9248725ebcedac3997a8d3da0d90a12a28c9179c6ba51f1658938ac30d0", size = 915777 }, + { url = "https://files.pythonhosted.org/packages/45/bd/8405d03371e335f02eb72e09dcf73307f8fd3095e4165cec6836346fe3db/nh3-0.2.20-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f7d564871833ddbe54df3aa59053b1110729d3a800cb7628ae8f42adb3d75208", size = 908614 }, + { url = "https://files.pythonhosted.org/packages/ee/f8/5d977f09cf82c1f22a864375f471db111530fc79c88efdf0659fe6d3d6bc/nh3-0.2.20-cp313-cp313t-win32.whl", hash = "sha256:d2a176fd4306b6f0f178a3f67fac91bd97a3a8d8fafb771c9b9ef675ba5c8886", size = 540482 }, + { url = "https://files.pythonhosted.org/packages/c5/f4/e34afe5fd8bed1920eac2974c9c853f548b4b65c139444285ffd2a68495d/nh3-0.2.20-cp313-cp313t-win_amd64.whl", hash = "sha256:6ed834c68452a600f517dd3e1534dbfaff1f67f98899fecf139a055a25d99150", size = 541302 }, + { url = "https://files.pythonhosted.org/packages/92/08/5e3b61eed1bc0efeb330ddc5cf5194f28a0b7be7943aa20bd44cfe14650b/nh3-0.2.20-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:76e2f603b30c02ff6456b233a83fc377dedab6a50947b04e960a6b905637b776", size = 1202141 }, + { url = "https://files.pythonhosted.org/packages/29/d2/3377f8006c71e95e007b07b5bfcac22c9de4744ca3efb23b396d3deb9581/nh3-0.2.20-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:181063c581defe683bd4bb78188ac9936d208aebbc74c7f7c16b6a32ae2ebb38", size = 760699 }, + { url = "https://files.pythonhosted.org/packages/37/d7/7077f925d7d680d53dcb6e18a4af13d1a7da59761c06c193bfa249a7470a/nh3-0.2.20-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:231addb7643c952cd6d71f1c8702d703f8fe34afcb20becb3efb319a501a12d7", size = 747353 }, + { url = "https://files.pythonhosted.org/packages/cb/59/6b2f32af477aae81f1454a7f6ef490ebc3c22dd9e1370e73fcfe243dc07a/nh3-0.2.20-cp38-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:1b9a8340a0aab991c68a5ca938d35ef4a8a3f4bf1b455da8855a40bee1fa0ace", size = 854125 }, + { url = "https://files.pythonhosted.org/packages/5b/f2/c3d2f7b801477b8b387b51fbefd16dc7ade888aeac547f18ba0558fd6f48/nh3-0.2.20-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:10317cd96fe4bbd4eb6b95f3920b71c902157ad44fed103fdcde43e3b8ee8be6", size = 817453 }, + { url = "https://files.pythonhosted.org/packages/42/4d/f7e3a35506a0eba6eedafc21ad52773985511eb838812e9f96354831ad3c/nh3-0.2.20-cp38-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8698db4c04b140800d1a1cd3067fda399e36e1e2b8fc1fe04292a907350a3e9b", size = 891694 }, + { url = "https://files.pythonhosted.org/packages/e6/0e/c499453c296fb40366e3069cd68fde77a10f0a30a17b9d3b491eb3ebc5bf/nh3-0.2.20-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3eb04b9c3deb13c3a375ea39fd4a3c00d1f92e8fb2349f25f1e3e4506751774b", size = 744388 }, + { url = "https://files.pythonhosted.org/packages/18/67/c3de8022ba2719bdbbdd3704d1e32dbc7d3f8ac8646247711645fc90d051/nh3-0.2.20-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:92f3f1c4f47a2c6f3ca7317b1d5ced05bd29556a75d3a4e2715652ae9d15c05d", size = 764831 }, + { url = "https://files.pythonhosted.org/packages/f0/14/a4ea40e2439717d11c3104fc2dc0ac412301b7aeb81d6a3d0e6505c77e7d/nh3-0.2.20-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ddefa9fd6794a87e37d05827d299d4b53a3ec6f23258101907b96029bfef138a", size = 923334 }, + { url = "https://files.pythonhosted.org/packages/ed/ae/e8ee8afaf67903dd304f390056d1ea620327524e2ad66127a331b14d5d98/nh3-0.2.20-cp38-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:ce3731c8f217685d33d9268362e5b4f770914e922bba94d368ab244a59a6c397", size = 994873 }, + { url = "https://files.pythonhosted.org/packages/20/b5/02122cfe3b36cf0ba0fcd73a04fd462e1f7a9d91b456f6e0b70e46df21c7/nh3-0.2.20-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:09f037c02fc2c43b211ff1523de32801dcfb0918648d8e651c36ef890f1731ec", size = 915707 }, + { url = "https://files.pythonhosted.org/packages/47/d3/5df43cc3570cdc9eb1dc79a39191f89fedf8bcefd8d30a161ff1dffb146c/nh3-0.2.20-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:813f1c8012dd64c990514b795508abb90789334f76a561fa0fd4ca32d2275330", size = 908539 }, + { url = "https://files.pythonhosted.org/packages/4f/fd/aa000f6c76a832c488eac26f20d2e8a221ba2b965efce692f14ebc4290bf/nh3-0.2.20-cp38-abi3-win32.whl", hash = "sha256:47b2946c0e13057855209daeffb45dc910bd0c55daf10190bb0b4b60e2999784", size = 540439 }, + { url = "https://files.pythonhosted.org/packages/19/31/d65594efd3b42b1de2335d576eb77525691fc320dbf8617948ee05c008e5/nh3-0.2.20-cp38-abi3-win_amd64.whl", hash = "sha256:da87573f03084edae8eb87cfe811ec338606288f81d333c07d2a9a0b9b976c0b", size = 541249 }, +] + +[[package]] +name = "outcome" +version = "1.3.0.post0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/98/df/77698abfac98571e65ffeb0c1fba8ffd692ab8458d617a0eed7d9a8d38f2/outcome-1.3.0.post0.tar.gz", hash = "sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8", size = 21060 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/55/8b/5ab7257531a5d830fc8000c476e63c935488d74609b50f9384a643ec0a62/outcome-1.3.0.post0-py2.py3-none-any.whl", hash = "sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b", size = 10692 }, +] + +[[package]] +name = "packaging" +version = "24.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f", size = 163950 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451 }, +] + +[[package]] +name = "pathspec" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191 }, +] + +[[package]] +name = "pillow" +version = "11.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f3/af/c097e544e7bd278333db77933e535098c259609c4eb3b85381109602fb5b/pillow-11.1.0.tar.gz", hash = "sha256:368da70808b36d73b4b390a8ffac11069f8a5c85f29eff1f1b01bcf3ef5b2a20", size = 46742715 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/dd/d6/2000bfd8d5414fb70cbbe52c8332f2283ff30ed66a9cde42716c8ecbe22c/pillow-11.1.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:e06695e0326d05b06833b40b7ef477e475d0b1ba3a6d27da1bb48c23209bf457", size = 3229968 }, + { url = "https://files.pythonhosted.org/packages/d9/45/3fe487010dd9ce0a06adf9b8ff4f273cc0a44536e234b0fad3532a42c15b/pillow-11.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96f82000e12f23e4f29346e42702b6ed9a2f2fea34a740dd5ffffcc8c539eb35", size = 3101806 }, + { url = "https://files.pythonhosted.org/packages/e3/72/776b3629c47d9d5f1c160113158a7a7ad177688d3a1159cd3b62ded5a33a/pillow-11.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3cd561ded2cf2bbae44d4605837221b987c216cff94f49dfeed63488bb228d2", size = 4322283 }, + { url = "https://files.pythonhosted.org/packages/e4/c2/e25199e7e4e71d64eeb869f5b72c7ddec70e0a87926398785ab944d92375/pillow-11.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f189805c8be5ca5add39e6f899e6ce2ed824e65fb45f3c28cb2841911da19070", size = 4402945 }, + { url = "https://files.pythonhosted.org/packages/c1/ed/51d6136c9d5911f78632b1b86c45241c712c5a80ed7fa7f9120a5dff1eba/pillow-11.1.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:dd0052e9db3474df30433f83a71b9b23bd9e4ef1de13d92df21a52c0303b8ab6", size = 4361228 }, + { url = "https://files.pythonhosted.org/packages/48/a4/fbfe9d5581d7b111b28f1d8c2762dee92e9821bb209af9fa83c940e507a0/pillow-11.1.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:837060a8599b8f5d402e97197d4924f05a2e0d68756998345c829c33186217b1", size = 4484021 }, + { url = "https://files.pythonhosted.org/packages/39/db/0b3c1a5018117f3c1d4df671fb8e47d08937f27519e8614bbe86153b65a5/pillow-11.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:aa8dd43daa836b9a8128dbe7d923423e5ad86f50a7a14dc688194b7be5c0dea2", size = 4287449 }, + { url = "https://files.pythonhosted.org/packages/d9/58/bc128da7fea8c89fc85e09f773c4901e95b5936000e6f303222490c052f3/pillow-11.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0a2f91f8a8b367e7a57c6e91cd25af510168091fb89ec5146003e424e1558a96", size = 4419972 }, + { url = "https://files.pythonhosted.org/packages/5f/bb/58f34379bde9fe197f51841c5bbe8830c28bbb6d3801f16a83b8f2ad37df/pillow-11.1.0-cp311-cp311-win32.whl", hash = "sha256:c12fc111ef090845de2bb15009372175d76ac99969bdf31e2ce9b42e4b8cd88f", size = 2291201 }, + { url = "https://files.pythonhosted.org/packages/3a/c6/fce9255272bcf0c39e15abd2f8fd8429a954cf344469eaceb9d0d1366913/pillow-11.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:fbd43429d0d7ed6533b25fc993861b8fd512c42d04514a0dd6337fb3ccf22761", size = 2625686 }, + { url = "https://files.pythonhosted.org/packages/c8/52/8ba066d569d932365509054859f74f2a9abee273edcef5cd75e4bc3e831e/pillow-11.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:f7955ecf5609dee9442cbface754f2c6e541d9e6eda87fad7f7a989b0bdb9d71", size = 2375194 }, + { url = "https://files.pythonhosted.org/packages/95/20/9ce6ed62c91c073fcaa23d216e68289e19d95fb8188b9fb7a63d36771db8/pillow-11.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2062ffb1d36544d42fcaa277b069c88b01bb7298f4efa06731a7fd6cc290b81a", size = 3226818 }, + { url = "https://files.pythonhosted.org/packages/b9/d8/f6004d98579a2596c098d1e30d10b248798cceff82d2b77aa914875bfea1/pillow-11.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a85b653980faad27e88b141348707ceeef8a1186f75ecc600c395dcac19f385b", size = 3101662 }, + { url = "https://files.pythonhosted.org/packages/08/d9/892e705f90051c7a2574d9f24579c9e100c828700d78a63239676f960b74/pillow-11.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9409c080586d1f683df3f184f20e36fb647f2e0bc3988094d4fd8c9f4eb1b3b3", size = 4329317 }, + { url = "https://files.pythonhosted.org/packages/8c/aa/7f29711f26680eab0bcd3ecdd6d23ed6bce180d82e3f6380fb7ae35fcf3b/pillow-11.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7fdadc077553621911f27ce206ffcbec7d3f8d7b50e0da39f10997e8e2bb7f6a", size = 4412999 }, + { url = "https://files.pythonhosted.org/packages/c8/c4/8f0fe3b9e0f7196f6d0bbb151f9fba323d72a41da068610c4c960b16632a/pillow-11.1.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:93a18841d09bcdd774dcdc308e4537e1f867b3dec059c131fde0327899734aa1", size = 4368819 }, + { url = "https://files.pythonhosted.org/packages/38/0d/84200ed6a871ce386ddc82904bfadc0c6b28b0c0ec78176871a4679e40b3/pillow-11.1.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:9aa9aeddeed452b2f616ff5507459e7bab436916ccb10961c4a382cd3e03f47f", size = 4496081 }, + { url = "https://files.pythonhosted.org/packages/84/9c/9bcd66f714d7e25b64118e3952d52841a4babc6d97b6d28e2261c52045d4/pillow-11.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3cdcdb0b896e981678eee140d882b70092dac83ac1cdf6b3a60e2216a73f2b91", size = 4296513 }, + { url = "https://files.pythonhosted.org/packages/db/61/ada2a226e22da011b45f7104c95ebda1b63dcbb0c378ad0f7c2a710f8fd2/pillow-11.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:36ba10b9cb413e7c7dfa3e189aba252deee0602c86c309799da5a74009ac7a1c", size = 4431298 }, + { url = "https://files.pythonhosted.org/packages/e7/c4/fc6e86750523f367923522014b821c11ebc5ad402e659d8c9d09b3c9d70c/pillow-11.1.0-cp312-cp312-win32.whl", hash = "sha256:cfd5cd998c2e36a862d0e27b2df63237e67273f2fc78f47445b14e73a810e7e6", size = 2291630 }, + { url = "https://files.pythonhosted.org/packages/08/5c/2104299949b9d504baf3f4d35f73dbd14ef31bbd1ddc2c1b66a5b7dfda44/pillow-11.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:a697cd8ba0383bba3d2d3ada02b34ed268cb548b369943cd349007730c92bddf", size = 2626369 }, + { url = "https://files.pythonhosted.org/packages/37/f3/9b18362206b244167c958984b57c7f70a0289bfb59a530dd8af5f699b910/pillow-11.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:4dd43a78897793f60766563969442020e90eb7847463eca901e41ba186a7d4a5", size = 2375240 }, + { url = "https://files.pythonhosted.org/packages/b3/31/9ca79cafdce364fd5c980cd3416c20ce1bebd235b470d262f9d24d810184/pillow-11.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ae98e14432d458fc3de11a77ccb3ae65ddce70f730e7c76140653048c71bfcbc", size = 3226640 }, + { url = "https://files.pythonhosted.org/packages/ac/0f/ff07ad45a1f172a497aa393b13a9d81a32e1477ef0e869d030e3c1532521/pillow-11.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cc1331b6d5a6e144aeb5e626f4375f5b7ae9934ba620c0ac6b3e43d5e683a0f0", size = 3101437 }, + { url = "https://files.pythonhosted.org/packages/08/2f/9906fca87a68d29ec4530be1f893149e0cb64a86d1f9f70a7cfcdfe8ae44/pillow-11.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:758e9d4ef15d3560214cddbc97b8ef3ef86ce04d62ddac17ad39ba87e89bd3b1", size = 4326605 }, + { url = "https://files.pythonhosted.org/packages/b0/0f/f3547ee15b145bc5c8b336401b2d4c9d9da67da9dcb572d7c0d4103d2c69/pillow-11.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b523466b1a31d0dcef7c5be1f20b942919b62fd6e9a9be199d035509cbefc0ec", size = 4411173 }, + { url = "https://files.pythonhosted.org/packages/b1/df/bf8176aa5db515c5de584c5e00df9bab0713548fd780c82a86cba2c2fedb/pillow-11.1.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:9044b5e4f7083f209c4e35aa5dd54b1dd5b112b108648f5c902ad586d4f945c5", size = 4369145 }, + { url = "https://files.pythonhosted.org/packages/de/7c/7433122d1cfadc740f577cb55526fdc39129a648ac65ce64db2eb7209277/pillow-11.1.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:3764d53e09cdedd91bee65c2527815d315c6b90d7b8b79759cc48d7bf5d4f114", size = 4496340 }, + { url = "https://files.pythonhosted.org/packages/25/46/dd94b93ca6bd555588835f2504bd90c00d5438fe131cf01cfa0c5131a19d/pillow-11.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:31eba6bbdd27dde97b0174ddf0297d7a9c3a507a8a1480e1e60ef914fe23d352", size = 4296906 }, + { url = "https://files.pythonhosted.org/packages/a8/28/2f9d32014dfc7753e586db9add35b8a41b7a3b46540e965cb6d6bc607bd2/pillow-11.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b5d658fbd9f0d6eea113aea286b21d3cd4d3fd978157cbf2447a6035916506d3", size = 4431759 }, + { url = "https://files.pythonhosted.org/packages/33/48/19c2cbe7403870fbe8b7737d19eb013f46299cdfe4501573367f6396c775/pillow-11.1.0-cp313-cp313-win32.whl", hash = "sha256:f86d3a7a9af5d826744fabf4afd15b9dfef44fe69a98541f666f66fbb8d3fef9", size = 2291657 }, + { url = "https://files.pythonhosted.org/packages/3b/ad/285c556747d34c399f332ba7c1a595ba245796ef3e22eae190f5364bb62b/pillow-11.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:593c5fd6be85da83656b93ffcccc2312d2d149d251e98588b14fbc288fd8909c", size = 2626304 }, + { url = "https://files.pythonhosted.org/packages/e5/7b/ef35a71163bf36db06e9c8729608f78dedf032fc8313d19bd4be5c2588f3/pillow-11.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:11633d58b6ee5733bde153a8dafd25e505ea3d32e261accd388827ee987baf65", size = 2375117 }, + { url = "https://files.pythonhosted.org/packages/79/30/77f54228401e84d6791354888549b45824ab0ffde659bafa67956303a09f/pillow-11.1.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:70ca5ef3b3b1c4a0812b5c63c57c23b63e53bc38e758b37a951e5bc466449861", size = 3230060 }, + { url = "https://files.pythonhosted.org/packages/ce/b1/56723b74b07dd64c1010fee011951ea9c35a43d8020acd03111f14298225/pillow-11.1.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:8000376f139d4d38d6851eb149b321a52bb8893a88dae8ee7d95840431977081", size = 3106192 }, + { url = "https://files.pythonhosted.org/packages/e1/cd/7bf7180e08f80a4dcc6b4c3a0aa9e0b0ae57168562726a05dc8aa8fa66b0/pillow-11.1.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ee85f0696a17dd28fbcfceb59f9510aa71934b483d1f5601d1030c3c8304f3c", size = 4446805 }, + { url = "https://files.pythonhosted.org/packages/97/42/87c856ea30c8ed97e8efbe672b58c8304dee0573f8c7cab62ae9e31db6ae/pillow-11.1.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:dd0e081319328928531df7a0e63621caf67652c8464303fd102141b785ef9547", size = 4530623 }, + { url = "https://files.pythonhosted.org/packages/ff/41/026879e90c84a88e33fb00cc6bd915ac2743c67e87a18f80270dfe3c2041/pillow-11.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e63e4e5081de46517099dc30abe418122f54531a6ae2ebc8680bcd7096860eab", size = 4465191 }, + { url = "https://files.pythonhosted.org/packages/e5/fb/a7960e838bc5df57a2ce23183bfd2290d97c33028b96bde332a9057834d3/pillow-11.1.0-cp313-cp313t-win32.whl", hash = "sha256:dda60aa465b861324e65a78c9f5cf0f4bc713e4309f83bc387be158b077963d9", size = 2295494 }, + { url = "https://files.pythonhosted.org/packages/d7/6c/6ec83ee2f6f0fda8d4cf89045c6be4b0373ebfc363ba8538f8c999f63fcd/pillow-11.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ad5db5781c774ab9a9b2c4302bbf0c1014960a0a7be63278d13ae6fdf88126fe", size = 2631595 }, + { url = "https://files.pythonhosted.org/packages/cf/6c/41c21c6c8af92b9fea313aa47c75de49e2f9a467964ee33eb0135d47eb64/pillow-11.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:67cd427c68926108778a9005f2a04adbd5e67c442ed21d95389fe1d595458756", size = 2377651 }, +] + +[[package]] +name = "platformdirs" +version = "4.3.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/13/fc/128cc9cb8f03208bdbf93d3aa862e16d376844a14f9a0ce5cf4507372de4/platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907", size = 21302 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/a6/bc1012356d8ece4d66dd75c4b9fc6c1f6650ddd5991e421177d9f8f671be/platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb", size = 18439 }, +] + +[[package]] +name = "pluggy" +version = "1.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556 }, +] + +[[package]] +name = "prompt-toolkit" +version = "3.0.50" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "wcwidth" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a1/e1/bd15cb8ffdcfeeb2bdc215de3c3cffca11408d829e4b8416dcfe71ba8854/prompt_toolkit-3.0.50.tar.gz", hash = "sha256:544748f3860a2623ca5cd6d2795e7a14f3d0e1c3c9728359013f79877fc89bab", size = 429087 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e4/ea/d836f008d33151c7a1f62caf3d8dd782e4d15f6a43897f64480c2b8de2ad/prompt_toolkit-3.0.50-py3-none-any.whl", hash = "sha256:9b6427eb19e479d98acff65196a307c555eb567989e6d88ebbb1b509d9779198", size = 387816 }, +] + +[[package]] +name = "psycopg2" +version = "2.9.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/62/51/2007ea29e605957a17ac6357115d0c1a1b60c8c984951c19419b3474cdfd/psycopg2-2.9.10.tar.gz", hash = "sha256:12ec0b40b0273f95296233e8750441339298e6a572f7039da5b260e3c8b60e11", size = 385672 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/a2/c51ca3e667c34e7852157b665e3d49418e68182081060231d514dd823225/psycopg2-2.9.10-cp311-cp311-win32.whl", hash = "sha256:47c4f9875125344f4c2b870e41b6aad585901318068acd01de93f3677a6522c2", size = 1024538 }, + { url = "https://files.pythonhosted.org/packages/33/39/5a9a229bb5414abeb86e33b8fc8143ab0aecce5a7f698a53e31367d30caa/psycopg2-2.9.10-cp311-cp311-win_amd64.whl", hash = "sha256:0435034157049f6846e95103bd8f5a668788dd913a7c30162ca9503fdf542cb4", size = 1163736 }, + { url = "https://files.pythonhosted.org/packages/3d/16/4623fad6076448df21c1a870c93a9774ad8a7b4dd1660223b59082dd8fec/psycopg2-2.9.10-cp312-cp312-win32.whl", hash = "sha256:65a63d7ab0e067e2cdb3cf266de39663203d38d6a8ed97f5ca0cb315c73fe067", size = 1025113 }, + { url = "https://files.pythonhosted.org/packages/66/de/baed128ae0fc07460d9399d82e631ea31a1f171c0c4ae18f9808ac6759e3/psycopg2-2.9.10-cp312-cp312-win_amd64.whl", hash = "sha256:4a579d6243da40a7b3182e0430493dbd55950c493d8c68f4eec0b302f6bbf20e", size = 1163951 }, + { url = "https://files.pythonhosted.org/packages/ae/49/a6cfc94a9c483b1fa401fbcb23aca7892f60c7269c5ffa2ac408364f80dc/psycopg2-2.9.10-cp313-cp313-win_amd64.whl", hash = "sha256:91fd603a2155da8d0cfcdbf8ab24a2d54bca72795b90d2a3ed2b6da8d979dee2", size = 2569060 }, +] + +[[package]] +name = "pycparser" +version = "2.22" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", size = 172736 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc", size = 117552 }, +] + +[[package]] +name = "pygments" +version = "2.19.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293 }, +] + +[[package]] +name = "pyproject-api" +version = "1.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "packaging" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7e/66/fdc17e94486836eda4ba7113c0db9ac7e2f4eea1b968ee09de2fe75e391b/pyproject_api-1.9.0.tar.gz", hash = "sha256:7e8a9854b2dfb49454fae421cb86af43efbb2b2454e5646ffb7623540321ae6e", size = 22714 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b0/1d/92b7c765df46f454889d9610292b0ccab15362be3119b9a624458455e8d5/pyproject_api-1.9.0-py3-none-any.whl", hash = "sha256:326df9d68dea22d9d98b5243c46e3ca3161b07a1b9b18e213d1e24fd0e605766", size = 13131 }, +] + +[[package]] +name = "pyproject-hooks" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/82/28175b2414effca1cdac8dc99f76d660e7a4fb0ceefa4b4ab8f5f6742925/pyproject_hooks-1.2.0.tar.gz", hash = "sha256:1e859bd5c40fae9448642dd871adf459e5e2084186e8d2c2a79a824c970da1f8", size = 19228 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl", hash = "sha256:9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913", size = 10216 }, +] + +[[package]] +name = "pysocks" +version = "1.7.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bd/11/293dd436aea955d45fc4e8a35b6ae7270f5b8e00b53cf6c024c83b657a11/PySocks-1.7.1.tar.gz", hash = "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0", size = 284429 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8d/59/b4572118e098ac8e46e399a1dd0f2d85403ce8bbaad9ec79373ed6badaf9/PySocks-1.7.1-py3-none-any.whl", hash = "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5", size = 16725 }, +] + +[[package]] +name = "pytest" +version = "8.3.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/05/35/30e0d83068951d90a01852cb1cef56e5d8a09d20c7f511634cc2f7e0372a/pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761", size = 1445919 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/11/92/76a1c94d3afee238333bc0a42b82935dd8f9cf8ce9e336ff87ee14d9e1cf/pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6", size = 343083 }, +] + +[[package]] +name = "pytest-cache" +version = "1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "execnet" }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d1/15/082fd0428aab33d2bafa014f3beb241830427ba803a8912a5aaeaf3a5663/pytest-cache-1.0.tar.gz", hash = "sha256:be7468edd4d3d83f1e844959fd6e3fd28e77a481440a7118d430130ea31b07a9", size = 16242 } + +[[package]] +name = "pytest-cov" +version = "6.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "coverage", extra = ["toml"] }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/be/45/9b538de8cef30e17c7b45ef42f538a94889ed6a16f2387a6c89e73220651/pytest-cov-6.0.0.tar.gz", hash = "sha256:fde0b595ca248bb8e2d76f020b465f3b107c9632e6a1d1705f17834c89dcadc0", size = 66945 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/36/3b/48e79f2cd6a61dbbd4807b4ed46cb564b4fd50a76166b1c4ea5c1d9e2371/pytest_cov-6.0.0-py3-none-any.whl", hash = "sha256:eee6f1b9e61008bd34975a4d5bab25801eb31898b032dd55addc93e96fcaaa35", size = 22949 }, +] + +[[package]] +name = "pytest-django" +version = "4.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/02/c0/43c8b2528c24d7f1a48a47e3f7381f5ab2ae8c64634b0c3f4bd843063955/pytest_django-4.9.0.tar.gz", hash = "sha256:8bf7bc358c9ae6f6fc51b6cebb190fe20212196e6807121f11bd6a3b03428314", size = 84067 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/47/fe/54f387ee1b41c9ad59e48fb8368a361fad0600fe404315e31a12bacaea7d/pytest_django-4.9.0-py3-none-any.whl", hash = "sha256:1d83692cb39188682dbb419ff0393867e9904094a549a7d38a3154d5731b2b99", size = 23723 }, +] + +[[package]] +name = "pytest-echo" +version = "1.8.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4d/48/fc27028f166c25623ac0c1d401bce3a77662050edadb06d87bec1da2c63f/pytest_echo-1.8.1.tar.gz", hash = "sha256:7d765b4ddac93468fa1d303e70c48ad9e38479b4d122d5ae019919bb7fed0c2a", size = 14863 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b0/c6/50ae25410db72d9051329ca9337ffe90e9155858a64fcd1e7ce76b9168c6/pytest_echo-1.8.1-py2.py3-none-any.whl", hash = "sha256:2bc47fa7faf30fcbd39651667d69f199603599941cf3d6c5d296586799a19bfd", size = 5798 }, +] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892 }, +] + +[[package]] +name = "pytz" +version = "2025.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/5f/57/df1c9157c8d5a05117e455d66fd7cf6dbc46974f832b1058ed4856785d8a/pytz-2025.1.tar.gz", hash = "sha256:c2db42be2a2518b28e65f9207c4d05e6ff547d1efa4086469ef855e4ab70178e", size = 319617 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/eb/38/ac33370d784287baa1c3d538978b5e2ea064d4c1b93ffbd12826c190dd10/pytz-2025.1-py2.py3-none-any.whl", hash = "sha256:89dd22dca55b46eac6eda23b2d72721bf1bdfef212645d81513ef5d03038de57", size = 507930 }, +] + +[[package]] +name = "readme" +version = "0.7.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "readme-renderer" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e2/b5/831f3f29e64107a4222d7156a45f81bfdc6f0f29af9af96f3fe173a5d060/readme-0.7.1.tar.gz", hash = "sha256:32fbe1538a437da160fa4e4477270bfdcd8876e2e364d0d12898302644496231", size = 5914 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/de/9e/0efa8ecac772ad87a5674f8f8eb8e5939e45e95f48e7efa18415b160cd80/readme-0.7.1-py2.py3-none-any.whl", hash = "sha256:37482f34fc20bff7e4ad8a42f726dc902250d27a52e1196bb8fad4bdcfdcbbe4", size = 2988 }, +] + +[[package]] +name = "readme-renderer" +version = "44.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "docutils" }, + { name = "nh3" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5a/a9/104ec9234c8448c4379768221ea6df01260cd6c2ce13182d4eac531c8342/readme_renderer-44.0.tar.gz", hash = "sha256:8712034eabbfa6805cacf1402b4eeb2a73028f72d1166d6f5cb7f9c047c5d1e1", size = 32056 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e1/67/921ec3024056483db83953ae8e48079ad62b92db7880013ca77632921dd0/readme_renderer-44.0-py3-none-any.whl", hash = "sha256:2fbca89b81a08526aadf1357a8c2ae889ec05fb03f5da67f9769c9a592166151", size = 13310 }, +] + +[[package]] +name = "redis" +version = "5.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "async-timeout", marker = "python_full_version < '3.11.3'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/47/da/d283a37303a995cd36f8b92db85135153dc4f7a8e4441aa827721b442cfb/redis-5.2.1.tar.gz", hash = "sha256:16f2e22dff21d5125e8481515e386711a34cbec50f0e44413dd7d9c060a54e0f", size = 4608355 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/5f/fa26b9b2672cbe30e07d9a5bdf39cf16e3b80b42916757c5f92bca88e4ba/redis-5.2.1-py3-none-any.whl", hash = "sha256:ee7e1056b9aea0f04c6c2ed59452947f34c4940ee025f5dd83e6a6418b6989e4", size = 261502 }, +] + +[[package]] +name = "ruff" +version = "0.9.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/c0/17/529e78f49fc6f8076f50d985edd9a2cf011d1dbadb1cdeacc1d12afc1d26/ruff-0.9.4.tar.gz", hash = "sha256:6907ee3529244bb0ed066683e075f09285b38dd5b4039370df6ff06041ca19e7", size = 3599458 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b6/f8/3fafb7804d82e0699a122101b5bee5f0d6e17c3a806dcbc527bb7d3f5b7a/ruff-0.9.4-py3-none-linux_armv6l.whl", hash = "sha256:64e73d25b954f71ff100bb70f39f1ee09e880728efb4250c632ceed4e4cdf706", size = 11668400 }, + { url = "https://files.pythonhosted.org/packages/2e/a6/2efa772d335da48a70ab2c6bb41a096c8517ca43c086ea672d51079e3d1f/ruff-0.9.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6ce6743ed64d9afab4fafeaea70d3631b4d4b28b592db21a5c2d1f0ef52934bf", size = 11628395 }, + { url = "https://files.pythonhosted.org/packages/dc/d7/cd822437561082f1c9d7225cc0d0fbb4bad117ad7ac3c41cd5d7f0fa948c/ruff-0.9.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:54499fb08408e32b57360f6f9de7157a5fec24ad79cb3f42ef2c3f3f728dfe2b", size = 11090052 }, + { url = "https://files.pythonhosted.org/packages/9e/67/3660d58e893d470abb9a13f679223368ff1684a4ef40f254a0157f51b448/ruff-0.9.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37c892540108314a6f01f105040b5106aeb829fa5fb0561d2dcaf71485021137", size = 11882221 }, + { url = "https://files.pythonhosted.org/packages/79/d1/757559995c8ba5f14dfec4459ef2dd3fcea82ac43bc4e7c7bf47484180c0/ruff-0.9.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:de9edf2ce4b9ddf43fd93e20ef635a900e25f622f87ed6e3047a664d0e8f810e", size = 11424862 }, + { url = "https://files.pythonhosted.org/packages/c0/96/7915a7c6877bb734caa6a2af424045baf6419f685632469643dbd8eb2958/ruff-0.9.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:87c90c32357c74f11deb7fbb065126d91771b207bf9bfaaee01277ca59b574ec", size = 12626735 }, + { url = "https://files.pythonhosted.org/packages/0e/cc/dadb9b35473d7cb17c7ffe4737b4377aeec519a446ee8514123ff4a26091/ruff-0.9.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:56acd6c694da3695a7461cc55775f3a409c3815ac467279dfa126061d84b314b", size = 13255976 }, + { url = "https://files.pythonhosted.org/packages/5f/c3/ad2dd59d3cabbc12df308cced780f9c14367f0321e7800ca0fe52849da4c/ruff-0.9.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e0c93e7d47ed951b9394cf352d6695b31498e68fd5782d6cbc282425655f687a", size = 12752262 }, + { url = "https://files.pythonhosted.org/packages/c7/17/5f1971e54bd71604da6788efd84d66d789362b1105e17e5ccc53bba0289b/ruff-0.9.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1d4c8772670aecf037d1bf7a07c39106574d143b26cfe5ed1787d2f31e800214", size = 14401648 }, + { url = "https://files.pythonhosted.org/packages/30/24/6200b13ea611b83260501b6955b764bb320e23b2b75884c60ee7d3f0b68e/ruff-0.9.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfc5f1d7afeda8d5d37660eeca6d389b142d7f2b5a1ab659d9214ebd0e025231", size = 12414702 }, + { url = "https://files.pythonhosted.org/packages/34/cb/f5d50d0c4ecdcc7670e348bd0b11878154bc4617f3fdd1e8ad5297c0d0ba/ruff-0.9.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:faa935fc00ae854d8b638c16a5f1ce881bc3f67446957dd6f2af440a5fc8526b", size = 11859608 }, + { url = "https://files.pythonhosted.org/packages/d6/f4/9c8499ae8426da48363bbb78d081b817b0f64a9305f9b7f87eab2a8fb2c1/ruff-0.9.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a6c634fc6f5a0ceae1ab3e13c58183978185d131a29c425e4eaa9f40afe1e6d6", size = 11485702 }, + { url = "https://files.pythonhosted.org/packages/18/59/30490e483e804ccaa8147dd78c52e44ff96e1c30b5a95d69a63163cdb15b/ruff-0.9.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:433dedf6ddfdec7f1ac7575ec1eb9844fa60c4c8c2f8887a070672b8d353d34c", size = 12067782 }, + { url = "https://files.pythonhosted.org/packages/3d/8c/893fa9551760b2f8eb2a351b603e96f15af167ceaf27e27ad873570bc04c/ruff-0.9.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:d612dbd0f3a919a8cc1d12037168bfa536862066808960e0cc901404b77968f0", size = 12483087 }, + { url = "https://files.pythonhosted.org/packages/23/15/f6751c07c21ca10e3f4a51ea495ca975ad936d780c347d9808bcedbd7182/ruff-0.9.4-py3-none-win32.whl", hash = "sha256:db1192ddda2200671f9ef61d9597fcef89d934f5d1705e571a93a67fb13a4402", size = 9852302 }, + { url = "https://files.pythonhosted.org/packages/12/41/2d2d2c6a72e62566f730e49254f602dfed23019c33b5b21ea8f8917315a1/ruff-0.9.4-py3-none-win_amd64.whl", hash = "sha256:05bebf4cdbe3ef75430d26c375773978950bbf4ee3c95ccb5448940dc092408e", size = 10850051 }, + { url = "https://files.pythonhosted.org/packages/c6/e6/3d6ec3bc3d254e7f005c543a661a41c3e788976d0e52a1ada195bd664344/ruff-0.9.4-py3-none-win_arm64.whl", hash = "sha256:585792f1e81509e38ac5123492f8875fbc36f3ede8185af0a26df348e5154f41", size = 10078251 }, +] + +[[package]] +name = "selenium" +version = "4.28.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "trio" }, + { name = "trio-websocket" }, + { name = "typing-extensions" }, + { name = "urllib3", extra = ["socks"] }, + { name = "websocket-client" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/88/38/d62d4e8da649ad699b02eb1e95c3cfc20ff400744b9417b9093c5daebd4b/selenium-4.28.1.tar.gz", hash = "sha256:0072d08670d7ec32db901bd0107695a330cecac9f196e3afb3fa8163026e022a", size = 981633 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/9f/34d0ec09b0dd6fb7b08b93eb4b7b80049e0b9db0ba7f81ad814c9be78b8f/selenium-4.28.1-py3-none-any.whl", hash = "sha256:4238847e45e24e4472cfcf3554427512c7aab9443396435b1623ef406fff1cc1", size = 9530373 }, +] + +[[package]] +name = "setuptools" +version = "75.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/92/ec/089608b791d210aec4e7f97488e67ab0d33add3efccb83a056cbafe3a2a6/setuptools-75.8.0.tar.gz", hash = "sha256:c5afc8f407c626b8313a86e10311dd3f661c6cd9c09d4bf8c15c0e11f9f2b0e6", size = 1343222 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/8a/b9dc7678803429e4a3bc9ba462fa3dd9066824d3c607490235c6a796be5a/setuptools-75.8.0-py3-none-any.whl", hash = "sha256:e3982f444617239225d675215d51f6ba05f845d4eec313da4418fdbb56fb27e3", size = 1228782 }, +] + +[[package]] +name = "six" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050 }, +] + +[[package]] +name = "sniffio" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 }, +] + +[[package]] +name = "sortedcontainers" +version = "2.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e8/c4/ba2f8066cceb6f23394729afe52f3bf7adec04bf9ed2c820b39e19299111/sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", size = 30594 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575 }, +] + +[[package]] +name = "soupsieve" +version = "2.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d7/ce/fbaeed4f9fb8b2daa961f90591662df6a86c1abf25c548329a86920aedfb/soupsieve-2.6.tar.gz", hash = "sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb", size = 101569 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/c2/fe97d779f3ef3b15f05c94a2f1e3d21732574ed441687474db9d342a7315/soupsieve-2.6-py3-none-any.whl", hash = "sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9", size = 36186 }, +] + +[[package]] +name = "tomli" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", size = 17175 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/43/ca/75707e6efa2b37c77dadb324ae7d9571cb424e61ea73fad7c56c2d14527f/tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249", size = 131077 }, + { url = "https://files.pythonhosted.org/packages/c7/16/51ae563a8615d472fdbffc43a3f3d46588c264ac4f024f63f01283becfbb/tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6", size = 123429 }, + { url = "https://files.pythonhosted.org/packages/f1/dd/4f6cd1e7b160041db83c694abc78e100473c15d54620083dbd5aae7b990e/tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a", size = 226067 }, + { url = "https://files.pythonhosted.org/packages/a9/6b/c54ede5dc70d648cc6361eaf429304b02f2871a345bbdd51e993d6cdf550/tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee", size = 236030 }, + { url = "https://files.pythonhosted.org/packages/1f/47/999514fa49cfaf7a92c805a86c3c43f4215621855d151b61c602abb38091/tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e", size = 240898 }, + { url = "https://files.pythonhosted.org/packages/73/41/0a01279a7ae09ee1573b423318e7934674ce06eb33f50936655071d81a24/tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4", size = 229894 }, + { url = "https://files.pythonhosted.org/packages/55/18/5d8bc5b0a0362311ce4d18830a5d28943667599a60d20118074ea1b01bb7/tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106", size = 245319 }, + { url = "https://files.pythonhosted.org/packages/92/a3/7ade0576d17f3cdf5ff44d61390d4b3febb8a9fc2b480c75c47ea048c646/tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8", size = 238273 }, + { url = "https://files.pythonhosted.org/packages/72/6f/fa64ef058ac1446a1e51110c375339b3ec6be245af9d14c87c4a6412dd32/tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff", size = 98310 }, + { url = "https://files.pythonhosted.org/packages/6a/1c/4a2dcde4a51b81be3530565e92eda625d94dafb46dbeb15069df4caffc34/tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b", size = 108309 }, + { url = "https://files.pythonhosted.org/packages/52/e1/f8af4c2fcde17500422858155aeb0d7e93477a0d59a98e56cbfe75070fd0/tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea", size = 132762 }, + { url = "https://files.pythonhosted.org/packages/03/b8/152c68bb84fc00396b83e7bbddd5ec0bd3dd409db4195e2a9b3e398ad2e3/tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8", size = 123453 }, + { url = "https://files.pythonhosted.org/packages/c8/d6/fc9267af9166f79ac528ff7e8c55c8181ded34eb4b0e93daa767b8841573/tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192", size = 233486 }, + { url = "https://files.pythonhosted.org/packages/5c/51/51c3f2884d7bab89af25f678447ea7d297b53b5a3b5730a7cb2ef6069f07/tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222", size = 242349 }, + { url = "https://files.pythonhosted.org/packages/ab/df/bfa89627d13a5cc22402e441e8a931ef2108403db390ff3345c05253935e/tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77", size = 252159 }, + { url = "https://files.pythonhosted.org/packages/9e/6e/fa2b916dced65763a5168c6ccb91066f7639bdc88b48adda990db10c8c0b/tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6", size = 237243 }, + { url = "https://files.pythonhosted.org/packages/b4/04/885d3b1f650e1153cbb93a6a9782c58a972b94ea4483ae4ac5cedd5e4a09/tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd", size = 259645 }, + { url = "https://files.pythonhosted.org/packages/9c/de/6b432d66e986e501586da298e28ebeefd3edc2c780f3ad73d22566034239/tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e", size = 244584 }, + { url = "https://files.pythonhosted.org/packages/1c/9a/47c0449b98e6e7d1be6cbac02f93dd79003234ddc4aaab6ba07a9a7482e2/tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98", size = 98875 }, + { url = "https://files.pythonhosted.org/packages/ef/60/9b9638f081c6f1261e2688bd487625cd1e660d0a85bd469e91d8db969734/tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4", size = 109418 }, + { url = "https://files.pythonhosted.org/packages/04/90/2ee5f2e0362cb8a0b6499dc44f4d7d48f8fff06d28ba46e6f1eaa61a1388/tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7", size = 132708 }, + { url = "https://files.pythonhosted.org/packages/c0/ec/46b4108816de6b385141f082ba99e315501ccd0a2ea23db4a100dd3990ea/tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c", size = 123582 }, + { url = "https://files.pythonhosted.org/packages/a0/bd/b470466d0137b37b68d24556c38a0cc819e8febe392d5b199dcd7f578365/tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13", size = 232543 }, + { url = "https://files.pythonhosted.org/packages/d9/e5/82e80ff3b751373f7cead2815bcbe2d51c895b3c990686741a8e56ec42ab/tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281", size = 241691 }, + { url = "https://files.pythonhosted.org/packages/05/7e/2a110bc2713557d6a1bfb06af23dd01e7dde52b6ee7dadc589868f9abfac/tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272", size = 251170 }, + { url = "https://files.pythonhosted.org/packages/64/7b/22d713946efe00e0adbcdfd6d1aa119ae03fd0b60ebed51ebb3fa9f5a2e5/tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140", size = 236530 }, + { url = "https://files.pythonhosted.org/packages/38/31/3a76f67da4b0cf37b742ca76beaf819dca0ebef26d78fc794a576e08accf/tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2", size = 258666 }, + { url = "https://files.pythonhosted.org/packages/07/10/5af1293da642aded87e8a988753945d0cf7e00a9452d3911dd3bb354c9e2/tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744", size = 243954 }, + { url = "https://files.pythonhosted.org/packages/5b/b9/1ed31d167be802da0fc95020d04cd27b7d7065cc6fbefdd2f9186f60d7bd/tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec", size = 98724 }, + { url = "https://files.pythonhosted.org/packages/c7/32/b0963458706accd9afcfeb867c0f9175a741bf7b19cd424230714d722198/tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69", size = 109383 }, + { url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257 }, +] + +[[package]] +name = "tox" +version = "4.24.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cachetools" }, + { name = "chardet" }, + { name = "colorama" }, + { name = "filelock" }, + { name = "packaging" }, + { name = "platformdirs" }, + { name = "pluggy" }, + { name = "pyproject-api" }, + { name = "virtualenv" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cf/7b/97f757e159983737bdd8fb513f4c263cd411a846684814ed5433434a1fa9/tox-4.24.1.tar.gz", hash = "sha256:083a720adbc6166fff0b7d1df9d154f9d00bfccb9403b8abf6bc0ee435d6a62e", size = 194742 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ab/04/b0d1c1b44c98583cab9eabb4acdba964fdf6b6c597c53cfb8870fd08cbbf/tox-4.24.1-py3-none-any.whl", hash = "sha256:57ba7df7d199002c6df8c2db9e6484f3de6ca8f42013c083ea2d4d1e5c6bdc75", size = 171829 }, +] + +[[package]] +name = "trio" +version = "0.28.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "cffi", marker = "implementation_name != 'pypy' and os_name == 'nt'" }, + { name = "idna" }, + { name = "outcome" }, + { name = "sniffio" }, + { name = "sortedcontainers" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b3/73/57efab729506a8d4b89814f1e356ec8f3369de0ed4fd7e7616974d09646d/trio-0.28.0.tar.gz", hash = "sha256:4e547896fe9e8a5658e54e4c7c5fa1db748cbbbaa7c965e7d40505b928c73c05", size = 580318 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b4/04/9954a59e1fb6732f5436225c9af963811d7b24ea62a8bf96991f2cb8c26e/trio-0.28.0-py3-none-any.whl", hash = "sha256:56d58977acc1635735a96581ec70513cc781b8b6decd299c487d3be2a721cd94", size = 486317 }, +] + +[[package]] +name = "trio-websocket" +version = "0.11.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "trio" }, + { name = "wsproto" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/dd/36/abad2385853077424a11b818d9fd8350d249d9e31d583cb9c11cd4c85eda/trio-websocket-0.11.1.tar.gz", hash = "sha256:18c11793647703c158b1f6e62de638acada927344d534e3c7628eedcb746839f", size = 26511 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/48/be/a9ae5f50cad5b6f85bd2574c2c923730098530096e170c1ce7452394d7aa/trio_websocket-0.11.1-py3-none-any.whl", hash = "sha256:520d046b0d030cf970b8b2b2e00c4c2245b3807853ecd44214acd33d74581638", size = 17408 }, +] + +[[package]] +name = "typing-extensions" +version = "4.12.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 }, +] + +[[package]] +name = "tzdata" +version = "2025.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/0f/fa4723f22942480be4ca9527bbde8d43f6c3f2fe8412f00e7f5f6746bc8b/tzdata-2025.1.tar.gz", hash = "sha256:24894909e88cdb28bd1636c6887801df64cb485bd593f2fd83ef29075a81d694", size = 194950 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0f/dd/84f10e23edd882c6f968c21c2434fe67bd4a528967067515feca9e611e5e/tzdata-2025.1-py2.py3-none-any.whl", hash = "sha256:7e127113816800496f027041c570f50bcd464a020098a3b6b199517772303639", size = 346762 }, +] + +[[package]] +name = "urllib3" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/aa/63/e53da845320b757bf29ef6a9062f5c669fe997973f966045cb019c3f4b66/urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d", size = 307268 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c8/19/4ec628951a74043532ca2cf5d97b7b14863931476d117c471e8e2b1eb39f/urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df", size = 128369 }, +] + +[package.optional-dependencies] +socks = [ + { name = "pysocks" }, +] + +[[package]] +name = "vine" +version = "5.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bd/e4/d07b5f29d283596b9727dd5275ccbceb63c44a1a82aa9e4bfd20426762ac/vine-5.1.0.tar.gz", hash = "sha256:8b62e981d35c41049211cf62a0a1242d8c1ee9bd15bb196ce38aefd6799e61e0", size = 48980 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/03/ff/7c0c86c43b3cbb927e0ccc0255cb4057ceba4799cd44ae95174ce8e8b5b2/vine-5.1.0-py3-none-any.whl", hash = "sha256:40fdf3c48b2cfe1c38a49e9ae2da6fda88e4794c810050a728bd7413811fb1dc", size = 9636 }, +] + +[[package]] +name = "virtualenv" +version = "20.29.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "distlib" }, + { name = "filelock" }, + { name = "platformdirs" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a7/ca/f23dcb02e161a9bba141b1c08aa50e8da6ea25e6d780528f1d385a3efe25/virtualenv-20.29.1.tar.gz", hash = "sha256:b8b8970138d32fb606192cb97f6cd4bb644fa486be9308fb9b63f81091b5dc35", size = 7658028 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/89/9b/599bcfc7064fbe5740919e78c5df18e5dceb0887e676256a1061bb5ae232/virtualenv-20.29.1-py3-none-any.whl", hash = "sha256:4e4cb403c0b0da39e13b46b1b2476e505cb0046b25f242bee80f62bf990b2779", size = 4282379 }, +] + +[[package]] +name = "waitress" +version = "3.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bf/cb/04ddb054f45faa306a230769e868c28b8065ea196891f09004ebace5b184/waitress-3.0.2.tar.gz", hash = "sha256:682aaaf2af0c44ada4abfb70ded36393f0e307f4ab9456a215ce0020baefc31f", size = 179901 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8d/57/a27182528c90ef38d82b636a11f606b0cbb0e17588ed205435f8affe3368/waitress-3.0.2-py3-none-any.whl", hash = "sha256:c56d67fd6e87c2ee598b76abdd4e96cfad1f24cacdea5078d382b1f9d7b5ed2e", size = 56232 }, +] + +[[package]] +name = "wcwidth" +version = "0.2.13" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6c/63/53559446a878410fc5a5974feb13d31d78d752eb18aeba59c7fef1af7598/wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5", size = 101301 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fd/84/fd2ba7aafacbad3c4201d395674fc6348826569da3c0937e75505ead3528/wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859", size = 34166 }, +] + +[[package]] +name = "webob" +version = "1.8.9" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "legacy-cgi", marker = "python_full_version >= '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/85/0b/1732085540b01f65e4e7999e15864fe14cd18b12a95731a43fd6fd11b26a/webob-1.8.9.tar.gz", hash = "sha256:ad6078e2edb6766d1334ec3dee072ac6a7f95b1e32ce10def8ff7f0f02d56589", size = 279775 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/50/bd/c336448be43d40be28e71f2e0f3caf7ccb28e2755c58f4c02c065bfe3e8e/WebOb-1.8.9-py2.py3-none-any.whl", hash = "sha256:45e34c58ed0c7e2ecd238ffd34432487ff13d9ad459ddfd77895e67abba7c1f9", size = 115364 }, +] + +[[package]] +name = "websocket-client" +version = "1.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e6/30/fba0d96b4b5fbf5948ed3f4681f7da2f9f64512e1d303f94b4cc174c24a5/websocket_client-1.8.0.tar.gz", hash = "sha256:3239df9f44da632f96012472805d40a23281a991027ce11d2f45a6f24ac4c3da", size = 54648 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/84/44687a29792a70e111c5c477230a72c4b957d88d16141199bf9acb7537a3/websocket_client-1.8.0-py3-none-any.whl", hash = "sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526", size = 58826 }, +] + +[[package]] +name = "webtest" +version = "3.0.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "beautifulsoup4" }, + { name = "waitress" }, + { name = "webob" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/26/c5/b25980d591b111f3898c27b140bc30977794157522a8da91f5bbb5de99b7/webtest-3.0.4.tar.gz", hash = "sha256:94778d19a37e5abd7388dad4d93874410ecced53a1739a8e5ff2dbcba1cfc0c4", size = 79395 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bc/69/df392f611d46b1ca32e829ba7db1a01d147875cfd51942c39c3f9dc1e48d/WebTest-3.0.4-py3-none-any.whl", hash = "sha256:5b3d8c69ac9057f17750ed5b45320a411423c2b4196bec6450961be98b03d8c1", size = 32149 }, +] + +[[package]] +name = "wsproto" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "h11" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c9/4a/44d3c295350d776427904d73c189e10aeae66d7f555bb2feee16d1e4ba5a/wsproto-1.2.0.tar.gz", hash = "sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065", size = 53425 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/58/e860788190eba3bcce367f74d29c4675466ce8dddfba85f7827588416f01/wsproto-1.2.0-py3-none-any.whl", hash = "sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736", size = 24226 }, +] + +[[package]] +name = "xlrd" +version = "2.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a6/b3/19a2540d21dea5f908304375bd43f5ed7a4c28a370dc9122c565423e6b44/xlrd-2.0.1.tar.gz", hash = "sha256:f72f148f54442c6b056bf931dbc34f986fd0c3b0b6b5a58d013c9aef274d0c88", size = 100259 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a6/0c/c2a72d51fe56e08a08acc85d13013558a2d793028ae7385448a6ccdfae64/xlrd-2.0.1-py2.py3-none-any.whl", hash = "sha256:6a33ee89877bd9abc1158129f6e94be74e2679636b8a205b43b85206c3f0bbdd", size = 96531 }, +] + +[[package]] +name = "xlwt" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/06/97/56a6f56ce44578a69343449aa5a0d98eefe04085d69da539f3034e2cd5c1/xlwt-1.3.0.tar.gz", hash = "sha256:c59912717a9b28f1a3c2a98fd60741014b06b043936dcecbc113eaaada156c88", size = 153929 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/44/48/def306413b25c3d01753603b1a222a011b8621aed27cd7f89cbc27e6b0f4/xlwt-1.3.0-py2.py3-none-any.whl", hash = "sha256:a082260524678ba48a297d922cc385f58278b8aa68741596a87de01a9c628b2e", size = 99981 }, +] From 43ccc68ae0393f62653ecefdae72a9f4fbb7f9f3 Mon Sep 17 00:00:00 2001 From: Stefano Apostolico Date: Fri, 7 Feb 2025 22:18:01 +0100 Subject: [PATCH 02/14] updates - add typing - add hatch version management - add github actions --- .bumpversion.cfg | 16 - .github/workflows/test.yml | 56 +- .gitignore | 7 +- MANIFEST.in | 6 +- pyproject.toml | 64 +- src/adminactions/__init__.py | 6 +- src/adminactions/compat.py | 15 +- .../templates/adminactions/bulk_update.html | 8 +- .../adminactions/bulk_update_results.html | 10 +- .../templates/adminactions/byrows_update.html | 16 +- .../templates/adminactions/charts.html | 10 +- .../templates/adminactions/duplicates.html | 14 +- .../templates/adminactions/export_csv.html | 14 +- .../adminactions/export_fixture.html | 4 +- .../templates/adminactions/export_xls.html | 14 +- .../adminactions/helpers/import_fixture.html | 2 +- .../templates/adminactions/mass_update.html | 8 +- .../templates/adminactions/merge_preview.html | 10 +- tox.ini | 25 +- uv.lock | 825 ++++++++++++++++-- 20 files changed, 923 insertions(+), 207 deletions(-) delete mode 100644 .bumpversion.cfg diff --git a/.bumpversion.cfg b/.bumpversion.cfg deleted file mode 100644 index 6b60f498..00000000 --- a/.bumpversion.cfg +++ /dev/null @@ -1,16 +0,0 @@ -[bumpversion] -current_version = 2.3.0 -parse = (?P\d+)\.(?P\d+)\.(?P\d+) -serialize = {major}.{minor}.{patch} -commit = False -tag = False -allow_dirty = True - -[bumpversion:file:src/adminactions/__init__.py] - -[bumpversion:part:release] -optional_value = final -values = - dev - rc - final diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 111ea1d6..851f8562 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -30,31 +30,47 @@ jobs: strategy: fail-fast: false matrix: - python-version: [ "3.10", "3.11", "3.12" ] - django-version: [ "3.2", "4.2", "5.0" ] +# python-version: [ "3.10", "3.11", "3.12" ] +# django-version: [ "3.2", "4.2", "5.0" ] + python-version: [ "312" ] + django-version: [ "51" ] env: PY_VER: ${{ matrix.python-version}} DJ_VER: ${{ matrix.django-version}} CELERY_BROKER_URL: redis://redis:6379/0 CELERY_ALWAYS_EAGER: true steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Install the latest version of uv + uses: astral-sh/setup-uv@v5 + with: + enable-cache: true + cache-dependency-glob: "pyproject.toml" + github-token: ${{ secrets.GITHUB_TOKEN }} - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} + - name: Install tox + run: uv tool install --python-preference only-managed --python 3.13 tox --with tox-uv - - name: Install dependencies - run: python -m pip install --upgrade pip .[test] "django==${DJ_VER}.*" - - - name: Test with - run: py.test tests/ -v - - - uses: codecov/codecov-action@v1 - with: -# files: ./coverage1.xml,./coverage2.xml # optional -# flags: unittests # optional -# name: codecov-umbrella # optional -# fail_ci_if_error: true # optional (default = false) - verbose: true # optional (default = false) + - name: Install Python + if: matrix.python-version != '3.13' + run: uv python install --python-preference only-managed ${{ matrix.python-version}} + + - name: Setup test suite ${{ env.DJ_VER }}-${{ env.PY_VER }} + run: tox run -vv --notest --skip-missing-interpreters false -e d${{ env.DJ_VER }}-py${{ env.PY_VER }} + + - name: Run test suite + run: + COV_CMD=$(if [${{ env.DJ_VER }}-${{ env.PY_VER }}} == 51-312 ]; then echo "--cov=pytest_echo --cov-report=xml"; else echo ; fi) + tox run --skip-pkg-install -e d${{ env.DJ_VER }}-py${{ env.PY_VER }} $COV_CMD + env: + PYTEST_ADDOPTS: "-vv --durations=20" + DIFF_AGAINST: HEAD + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v5 + if: ${{ success() && matrix.python-version == 3.13 }} + with: + env_vars: OS + name: codecov-pytest-order + token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.gitignore b/.gitignore index 2aebfd35..237793c6 100644 --- a/.gitignore +++ b/.gitignore @@ -5,15 +5,12 @@ *.pyc *.egg-info *.sqlite +src/adminactions/version.py /dist /build /docs/build /MANIFEST coverage.xml sonar-project.properties -.scannerwork -Pipfile -Pipfile.lock -poetry.lock .venv/ -pdm.lock +uv.lock diff --git a/MANIFEST.in b/MANIFEST.in index 61e5f1de..23b1afbf 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,15 +1,11 @@ -include README.rst +include README.md include MANIFEST.in include AUTHORS.rst include CHANGES include LICENSE -include setup.py -include setup.cfg include tox.ini include *.py -include Makefile -exclude .bumpversion.cfg exclude .editorconfig exclude manage.py exclude .* diff --git a/pyproject.toml b/pyproject.toml index ef734259..b95de619 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,13 +1,22 @@ +[build-system] +build-backend = "hatchling.build" +requires = [ + "hatch-vcs>=0.4", + "hatchling>=1.25", +] + [project] name = "django-adminactions" -version = "2.3.0" description = "Collections of useful actions to use with django.contrib.admin.ModelAdmin" readme = "README.md" -license = { text = "MIT" } +license.file = "LICENSE" +maintainers = [ + { name = "Stefano Apostolico", email = "s.apostolico@gmail.com" }, +] authors = [ { name = "sax", email = "s.apostolico@gmail.com" }, ] -requires-python = ">=3.11.0" +requires-python = ">=3.9" classifiers = [ "Environment :: Web Environment", "Framework :: Django", @@ -17,11 +26,16 @@ classifiers = [ "Intended Audience :: Developers", "Operating System :: OS Independent", "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", ] +dynamic = [ + "version", +] dependencies = [ "pytz", "xlrd>=0.9.2", @@ -34,23 +48,22 @@ urls.Homepage = "https://github.com/saxix/django-adminactions" [dependency-groups] dev = [ - "black>=25.1", - "celery>=5.4", - "check-manifest>=0.50", - "django-admin-extra-urls>=4.1.1", - "django-dynamic-fixture>=4.0.1", - "django-environ>=0.12", - "django-webtest>1.9.6", - "mock>=1.0.1", - "modernize>=0.8", - "mypy>=1.15", - "pillow>=11.1", - "psycopg2>=2.9.10", - "pytest>=8.3.4", - "pytest-cache>=1", - "pytest-cov>=6", - "pytest-django>=4.9", - "pytest-echo>=1.8.1", + "celery", + "check-manifest", + "django-admin-extra-urls", + "django-dynamic-fixture", + "django-environ", + "django-webtest", + "mock", + "modernize", + "mypy", + "pillow", + "psycopg2", + "pytest", + "pytest-cache", + "pytest-cov", + "pytest-django", + "pytest-echo", "readme>=0.7.1", "redis>=5.2.1", "ruff>=0.9.4", @@ -59,9 +72,18 @@ dev = [ "tox>=4.2", ] +[tool.hatch] +build.hooks.vcs.version-file = "src/adminactions/version.py" +version.source = "vcs" + [tool.ruff] target-version = "py311" line-length = 120 +exclude = [ + "docs", + "manage.py", + "tests", +] format.preview = true format.docstring-code-line-length = 100 format.docstring-code-format = true @@ -100,7 +122,6 @@ lint.ignore = [ "SLF", "TRY", "UP", - ] lint.per-file-ignores."docs/conf.py" = [ "A001", # @@ -113,6 +134,7 @@ lint.per-file-ignores."tests/**/*.py" = [ "FBT", # don"t care about booleans as positional arguments in tests "INP001", # no implicit namespace "PLR2004", # Magic value used in comparison, consider replacing with a constant variable + "PT", "S101", # asserts allowed in tests... "S603", # `subprocess` call: check for execution of untrusted input ] diff --git a/src/adminactions/__init__.py b/src/adminactions/__init__.py index 791f2d72..d93a8a2a 100644 --- a/src/adminactions/__init__.py +++ b/src/adminactions/__init__.py @@ -1,3 +1,3 @@ -VERSION = __version__ = "2.3.0" -NAME = "django-adminactions" -default_app_config = "adminactions.apps.Config" +# VERSION = __version__ = "2.3.0" +# NAME = "django-adminactions" +# default_app_config = "adminactions.apps.Config" diff --git a/src/adminactions/compat.py b/src/adminactions/compat.py index 0cd65777..2ebed27e 100644 --- a/src/adminactions/compat.py +++ b/src/adminactions/compat.py @@ -1,12 +1,21 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING + import django.db.transaction as t +if TYPE_CHECKING: + from types import TracebackType + class NoCommit(t.Atomic): - def __exit__(self, exc_type, exc_value, traceback): - super().__exit__(Exception, Exception(), None) + def __exit__( + self, exc_type: type[BaseException] | None, exc_value: BaseException | None, traceback: TracebackType | None + ) -> None: + super().__exit__(Exception, Exception(), traceback) -def nocommit(using=None, savepoint=True, durable=False): +def nocommit(using: str | None = None, savepoint: bool = True, durable: bool = False) -> NoCommit: return NoCommit(using, savepoint, durable) diff --git a/src/adminactions/templates/adminactions/bulk_update.html b/src/adminactions/templates/adminactions/bulk_update.html index 82a3e597..85c5a077 100644 --- a/src/adminactions/templates/adminactions/bulk_update.html +++ b/src/adminactions/templates/adminactions/bulk_update.html @@ -1,12 +1,16 @@ {% extends "admin/change_form.html" %} {% load actions admin_modify i18n massupdate static %} {% block extrahead %}{{ block.super }} -{% endblock extrahead %} {% block breadcrumbs %}{% if not is_popup %} +{% endblock extrahead %} + +{% block breadcrumbs %}{% if not is_popup %} -{% endif %}{% endblock breadcrumbs %} {% block content %} {% if form.subject.errors %} +{% endif %}{% endblock breadcrumbs %} + +{% block content %} {% if form.subject.errors %}
    {% for error in form.subject.errors %}
  1. {{ error|escape }}
  2. diff --git a/src/adminactions/templates/adminactions/bulk_update_results.html b/src/adminactions/templates/adminactions/bulk_update_results.html index c1903821..95be5f71 100644 --- a/src/adminactions/templates/adminactions/bulk_update_results.html +++ b/src/adminactions/templates/adminactions/bulk_update_results.html @@ -1,13 +1,17 @@ {% extends "admin/change_form.html" %} {% load actions admin_modify i18n massupdate static %} {% block extrahead %}{{ block.super }} -{{ media }}{% endblock extrahead %} {% block breadcrumbs %}{% if not is_popup %} +{{ media }}{% endblock extrahead %} + +{% block breadcrumbs %}{% if not is_popup %} -{% endif %}{% endblock breadcrumbs %} {% block content %} +{% endif %}{% endblock breadcrumbs %} + +{% block content %}

    Bulk Update results {% if dry_run %}(simulated) {% endif %}

    diff --git a/src/adminactions/templates/adminactions/byrows_update.html b/src/adminactions/templates/adminactions/byrows_update.html index 4e95e62d..26eef7c8 100644 --- a/src/adminactions/templates/adminactions/byrows_update.html +++ b/src/adminactions/templates/adminactions/byrows_update.html @@ -20,16 +20,20 @@ type="text/javascript" src="{% static 'admin/js/jquery.init.js' %}" > -{% endblock extrahead %} {% block breadcrumbs %}{% if not is_popup %} +{% endblock extrahead %} + +{% block breadcrumbs %}{% if not is_popup %} -{% endif %}{% endblock breadcrumbs %} {% block content %} {% if formset.errors %} +{% endif %}{% endblock breadcrumbs %} + +{% block content %} {% if formset.errors %}

    - {% if formset.errors|length == 1 %}{% translate "Please correct the error below." %}{% else %}{% translate "Please correct the errors below." %}{%endif %} + {% if formset.errors|length == 1 %}{% translate "Please correct the error below." %}{% else %}{% translate "Please correct the errors below." %}{% endif %}

    {{ adminform.form.non_field_errors }} {% endif %} @@ -52,7 +56,7 @@ {% for field in form.visible_fields %} {% endfor %} @@ -60,7 +64,7 @@
    - {% if forloop.first %} {% for hidden in form.hidden_fields %} {{hidden}} {% endfor %} {% endif %} {{ field.errors.as_ul }} {{ field}} + {% if forloop.first %} {% for hidden in form.hidden_fields %} {{ hidden }} {% endfor %} {% endif %} {{ field.errors.as_ul }} {{ field }}
    {{ formset.management_form }} {% for hidden in actionform.hidden_fields %} - {{hidden }} {% endfor %} + {{ hidden }} {% endfor %} {% endblock content %} diff --git a/src/adminactions/templates/adminactions/charts.html b/src/adminactions/templates/adminactions/charts.html index f44911ec..c3c3e30d 100644 --- a/src/adminactions/templates/adminactions/charts.html +++ b/src/adminactions/templates/adminactions/charts.html @@ -26,14 +26,18 @@ src="{% static 'adminactions/js/jqplot/plugins/jqplot.categoryAxisRenderer.min.js' %}" > -{% endblock extrahead %} {% block breadcrumbs %}{% if not is_popup %} +{% endblock extrahead %} + +{% block breadcrumbs %}{% if not is_popup %} -{% endif %} {% endblock breadcrumbs %} {% block content %} +{% endif %} {% endblock breadcrumbs %} + +{% block content %}
    -{% csrf_token %}= diff --git a/src/adminactions/templates/adminactions/duplicates.html b/src/adminactions/templates/adminactions/duplicates.html index f9ba20f8..19ecc9ad 100644 --- a/src/adminactions/templates/adminactions/duplicates.html +++ b/src/adminactions/templates/adminactions/duplicates.html @@ -1,12 +1,18 @@ -{% extends "admin/change_form.html" %}{% load actions admin_modify i18n static%} -{% block extrahead %}{{ block.super }}{{ form.media }}{% endblock %} {% block breadcrumbs %}{% if not is_popup %} +{% extends "admin/change_form.html" %}{% load actions admin_modify i18n static %} +{% block extrahead %}{{ block.super }}{{ form.media }}{% endblock %} + +{% block breadcrumbs %}{% if not is_popup %} -{% endif %} {% endblock %} {% block coltype %}{% endblock %} {% block content %} +{% endif %} {% endblock breadcrumbs %} + +{% block coltype %}{% endblock %} + +{% block content %}
    {% if form %} diff --git a/src/adminactions/templates/adminactions/export_csv.html b/src/adminactions/templates/adminactions/export_csv.html index 63e4e6ef..d3894f54 100644 --- a/src/adminactions/templates/adminactions/export_csv.html +++ b/src/adminactions/templates/adminactions/export_csv.html @@ -34,13 +34,17 @@ }); })(django.jQuery); -{% endif %} {% endblock extrahead %} {% block breadcrumbs %}{% if not is_popup %} +{% endif %} {% endblock extrahead %} + +{% block breadcrumbs %}{% if not is_popup %} -{% endif %}{% endblock breadcrumbs %} {% block content %} {% if adminform.form.subject.errors %} +{% endif %}{% endblock breadcrumbs %} + +{% block content %} {% if adminform.form.subject.errors %}
      {% for error in adminform.form.subject.errors %}
    1. {{ error|escape }}
    2. @@ -122,7 +126,7 @@ - 1{% translate "for Monday through" %}7{% translate "for Sunday"%} + 1{% translate "for Monday through" %}7{% translate "for Sunday" %} @@ -163,7 +167,7 @@ W - {% translate "ISO-8601 week number of year, weeks starting on Monday (added in PHP 4.1.0)"%} + {% translate "ISO-8601 week number of year, weeks starting on Monday (added in PHP 4.1.0)" %} {% translate "Example:" %} 42 {% translate "(the 42nd week in the year)" %} @@ -236,7 +240,7 @@ L {% translate "Whether it's a leap year" %} - 1{% translate " if it is a leap year, " %}0 {% translate "otherwise."%} + 1{% translate " if it is a leap year, " %}0 {% translate "otherwise." %} diff --git a/src/adminactions/templates/adminactions/export_fixture.html b/src/adminactions/templates/adminactions/export_fixture.html index 310ed9a2..3324b1ae 100644 --- a/src/adminactions/templates/adminactions/export_fixture.html +++ b/src/adminactions/templates/adminactions/export_fixture.html @@ -4,7 +4,9 @@ {{ app_label|capfirst|escape }}{{ opts.verbose_name_plural|capfirst }} › {{ action_short_description|capfirst }}
    -{% endif %}{% endblock breadcrumbs %} {% block content %} {% if form.subject.errors %} +{% endif %}{% endblock breadcrumbs %} + +{% block content %} {% if form.subject.errors %}
      {% for error in form.subject.errors %}
    1. {{ error|escape }}
    2. diff --git a/src/adminactions/templates/adminactions/export_xls.html b/src/adminactions/templates/adminactions/export_xls.html index c95f54dc..7f918ff8 100644 --- a/src/adminactions/templates/adminactions/export_xls.html +++ b/src/adminactions/templates/adminactions/export_xls.html @@ -1,4 +1,4 @@ -{% extends "admin/change_form.html" %} {% load i18n admin_modify admin_urls %}{% load url from aa_compat %} {% block extrahead %}{{ block.super }} +{% extends "admin/change_form.html" %} {% load admin_modify admin_urls i18n %}{% load url from aa_compat %} {% block extrahead %}{{ block.super }} -{% endblock %} {% block breadcrumbs %}{% if not is_popup %} +{% endblock extrahead %} + +{% block breadcrumbs %}{% if not is_popup %} -{% endif %}{% endblock %} {% block content %} {% if adminform.form.subject.errors %} +{% endif %}{% endblock breadcrumbs %} + +{% block content %} {% if adminform.form.subject.errors %}
        {% for error in adminform.form.subject.errors %}
      1. {{ error|escape }}
      2. @@ -34,4 +38,4 @@
    -{% endblock %} +{% endblock content %} diff --git a/src/adminactions/templates/adminactions/helpers/import_fixture.html b/src/adminactions/templates/adminactions/helpers/import_fixture.html index 30f881db..843bc834 100644 --- a/src/adminactions/templates/adminactions/helpers/import_fixture.html +++ b/src/adminactions/templates/adminactions/helpers/import_fixture.html @@ -22,4 +22,4 @@ -{% endblock %} +{% endblock action-content %} diff --git a/src/adminactions/templates/adminactions/mass_update.html b/src/adminactions/templates/adminactions/mass_update.html index 363f1099..7edbbf3f 100644 --- a/src/adminactions/templates/adminactions/mass_update.html +++ b/src/adminactions/templates/adminactions/mass_update.html @@ -1,11 +1,13 @@ -{% extends "admin/change_form.html" %} {% load i18n admin_modify actions massupdate static %} {% block breadcrumbs %}{% if not is_popup %} +{% extends "admin/change_form.html" %} {% load actions admin_modify i18n massupdate static %} {% block breadcrumbs %}{% if not is_popup %} -{% endif %}{% endblock %} {% block content %} {% if form.subject.errors %} +{% endif %}{% endblock breadcrumbs %} + +{% block content %} {% if form.subject.errors %}
      {% for error in form.subject.errors %}
    1. {{ error|escape }}
    2. @@ -76,4 +78,4 @@ />
    -{% endblock %} +{% endblock content %} diff --git a/src/adminactions/templates/adminactions/merge_preview.html b/src/adminactions/templates/adminactions/merge_preview.html index 719bdd3b..4cdcc97a 100644 --- a/src/adminactions/templates/adminactions/merge_preview.html +++ b/src/adminactions/templates/adminactions/merge_preview.html @@ -1,4 +1,4 @@ -{% extends "admin/change_form.html" %} {% load i18n actions static merge %} {% block breadcrumbs %}{% if not is_popup %} +{% extends "admin/change_form.html" %} {% load actions i18n merge static %} {% block breadcrumbs %}{% if not is_popup %} -{% endif %}{% endblock %} {% block content %} +{% endif %}{% endblock breadcrumbs %} + +{% block content %}
    - {% csrf_token %} {% for f in adminform.form.hidden_fields %}{{ f }}{% endfor%} + {% csrf_token %} {% for f in adminform.form.hidden_fields %}{{ f }}{% endfor %} {% for f in adminform.form.action_fields %}{{ f }}{% endfor %} @@ -35,4 +37,4 @@
    -{% endblock %} +{% endblock content %} diff --git a/tox.ini b/tox.ini index 3c41b205..3d82d260 100644 --- a/tox.ini +++ b/tox.ini @@ -4,9 +4,8 @@ requires = tox-uv>=1.20.2 env_list = lint - docs - package - d{50, 42, 32}-py{313, 312, 311} + pkg_meta + d{51, 42, 32}-py{313, 312, 311, 310} [testenv] description = run the tests with pytest @@ -40,3 +39,23 @@ pass_env = PROGRAMDATA commands = pre-commit run --all-files --show-diff-on-failure + +[testenv:pkg_meta] +description = check that the long description is valid +skip_install = true +deps = + check-wheel-contents>=0.6 + twine>=5.1.1 + uv>=0.5 +commands = + uv build --sdist --wheel --out-dir {env_tmp_dir} . + twine check {env_tmp_dir}{/}* + check-wheel-contents --no-config {env_tmp_dir} + +[testenv:type] +description = run type check on code base +deps = + mypy==1.11.2 +commands = + mypy --strict src + mypy --strict tests diff --git a/uv.lock b/uv.lock index e82a6716..1a35e5eb 100644 --- a/uv.lock +++ b/uv.lock @@ -1,8 +1,9 @@ version = 1 -requires-python = ">=3.11.0" +requires-python = ">=3.8" resolution-markers = [ "python_full_version >= '3.13'", - "python_full_version < '3.13'", + "python_full_version >= '3.9' and python_full_version < '3.13'", + "python_full_version < '3.9'", ] [[package]] @@ -44,6 +45,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fc/30/d4986a882011f9df997a55e6becd864812ccfcd821d64aac8570ee39f719/attrs-25.1.0-py3-none-any.whl", hash = "sha256:c75a69e28a550a7e93789579c22aa26b0f5b83b75dc4e08fe092980051e1090a", size = 63152 }, ] +[[package]] +name = "backports-zoneinfo" +version = "0.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ad/85/475e514c3140937cf435954f78dedea1861aeab7662d11de232bdaa90655/backports.zoneinfo-0.2.1.tar.gz", hash = "sha256:fadbfe37f74051d024037f223b8e001611eac868b5c5b06144ef4d8b799862f2", size = 74098 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4a/6d/eca004eeadcbf8bd64cc96feb9e355536147f0577420b44d80c7cac70767/backports.zoneinfo-0.2.1-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:8961c0f32cd0336fb8e8ead11a1f8cd99ec07145ec2931122faaac1c8f7fd987", size = 35816 }, + { url = "https://files.pythonhosted.org/packages/c1/8f/9b1b920a6a95652463143943fa3b8c000cb0b932ab463764a6f2a2416560/backports.zoneinfo-0.2.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e81b76cace8eda1fca50e345242ba977f9be6ae3945af8d46326d776b4cf78d1", size = 72147 }, + { url = "https://files.pythonhosted.org/packages/1a/ab/3e941e3fcf1b7d3ab3d0233194d99d6a0ed6b24f8f956fc81e47edc8c079/backports.zoneinfo-0.2.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7b0a64cda4145548fed9efc10322770f929b944ce5cee6c0dfe0c87bf4c0c8c9", size = 74033 }, + { url = "https://files.pythonhosted.org/packages/c0/34/5fdb0a3a28841d215c255be8fc60b8666257bb6632193c86fd04b63d4a31/backports.zoneinfo-0.2.1-cp38-cp38-win32.whl", hash = "sha256:1b13e654a55cd45672cb54ed12148cd33628f672548f373963b0bff67b217328", size = 36803 }, + { url = "https://files.pythonhosted.org/packages/78/cc/e27fd6493bbce8dbea7e6c1bc861fe3d3bc22c4f7c81f4c3befb8ff5bfaf/backports.zoneinfo-0.2.1-cp38-cp38-win_amd64.whl", hash = "sha256:4a0f800587060bf8880f954dbef70de6c11bbe59c673c3d818921f042f9954a6", size = 38967 }, +] + +[package.optional-dependencies] +tzdata = [ + { name = "tzdata", marker = "python_full_version < '3.9'" }, +] + [[package]] name = "beautifulsoup4" version = "4.13.3" @@ -66,42 +85,17 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/30/da/43b15f28fe5f9e027b41c539abc5469052e9d48fd75f8ff094ba2a0ae767/billiard-4.2.1-py3-none-any.whl", hash = "sha256:40b59a4ac8806ba2c2369ea98d876bc6108b051c227baffd928c644d15d8f3cb", size = 86766 }, ] -[[package]] -name = "black" -version = "25.1.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "click" }, - { name = "mypy-extensions" }, - { name = "packaging" }, - { name = "pathspec" }, - { name = "platformdirs" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/94/49/26a7b0f3f35da4b5a65f081943b7bcd22d7002f5f0fb8098ec1ff21cb6ef/black-25.1.0.tar.gz", hash = "sha256:33496d5cd1222ad73391352b4ae8da15253c5de89b93a80b3e2c8d9a19ec2666", size = 649449 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7e/4f/87f596aca05c3ce5b94b8663dbfe242a12843caaa82dd3f85f1ffdc3f177/black-25.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a39337598244de4bae26475f77dda852ea00a93bd4c728e09eacd827ec929df0", size = 1614372 }, - { url = "https://files.pythonhosted.org/packages/e7/d0/2c34c36190b741c59c901e56ab7f6e54dad8df05a6272a9747ecef7c6036/black-25.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96c1c7cd856bba8e20094e36e0f948718dc688dba4a9d78c3adde52b9e6c2299", size = 1442865 }, - { url = "https://files.pythonhosted.org/packages/21/d4/7518c72262468430ead45cf22bd86c883a6448b9eb43672765d69a8f1248/black-25.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bce2e264d59c91e52d8000d507eb20a9aca4a778731a08cfff7e5ac4a4bb7096", size = 1749699 }, - { url = "https://files.pythonhosted.org/packages/58/db/4f5beb989b547f79096e035c4981ceb36ac2b552d0ac5f2620e941501c99/black-25.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:172b1dbff09f86ce6f4eb8edf9dede08b1fce58ba194c87d7a4f1a5aa2f5b3c2", size = 1428028 }, - { url = "https://files.pythonhosted.org/packages/83/71/3fe4741df7adf015ad8dfa082dd36c94ca86bb21f25608eb247b4afb15b2/black-25.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4b60580e829091e6f9238c848ea6750efed72140b91b048770b64e74fe04908b", size = 1650988 }, - { url = "https://files.pythonhosted.org/packages/13/f3/89aac8a83d73937ccd39bbe8fc6ac8860c11cfa0af5b1c96d081facac844/black-25.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e2978f6df243b155ef5fa7e558a43037c3079093ed5d10fd84c43900f2d8ecc", size = 1453985 }, - { url = "https://files.pythonhosted.org/packages/6f/22/b99efca33f1f3a1d2552c714b1e1b5ae92efac6c43e790ad539a163d1754/black-25.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b48735872ec535027d979e8dcb20bf4f70b5ac75a8ea99f127c106a7d7aba9f", size = 1783816 }, - { url = "https://files.pythonhosted.org/packages/18/7e/a27c3ad3822b6f2e0e00d63d58ff6299a99a5b3aee69fa77cd4b0076b261/black-25.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:ea0213189960bda9cf99be5b8c8ce66bb054af5e9e861249cd23471bd7b0b3ba", size = 1440860 }, - { url = "https://files.pythonhosted.org/packages/98/87/0edf98916640efa5d0696e1abb0a8357b52e69e82322628f25bf14d263d1/black-25.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f0b18a02996a836cc9c9c78e5babec10930862827b1b724ddfe98ccf2f2fe4f", size = 1650673 }, - { url = "https://files.pythonhosted.org/packages/52/e5/f7bf17207cf87fa6e9b676576749c6b6ed0d70f179a3d812c997870291c3/black-25.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:afebb7098bfbc70037a053b91ae8437c3857482d3a690fefc03e9ff7aa9a5fd3", size = 1453190 }, - { url = "https://files.pythonhosted.org/packages/e3/ee/adda3d46d4a9120772fae6de454c8495603c37c4c3b9c60f25b1ab6401fe/black-25.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:030b9759066a4ee5e5aca28c3c77f9c64789cdd4de8ac1df642c40b708be6171", size = 1782926 }, - { url = "https://files.pythonhosted.org/packages/cc/64/94eb5f45dcb997d2082f097a3944cfc7fe87e071907f677e80788a2d7b7a/black-25.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:a22f402b410566e2d1c950708c77ebf5ebd5d0d88a6a2e87c86d9fb48afa0d18", size = 1442613 }, - { url = "https://files.pythonhosted.org/packages/09/71/54e999902aed72baf26bca0d50781b01838251a462612966e9fc4891eadd/black-25.1.0-py3-none-any.whl", hash = "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717", size = 207646 }, -] - [[package]] name = "build" version = "1.2.2.post1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "os_name == 'nt'" }, + { name = "importlib-metadata", version = "8.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "importlib-metadata", version = "8.6.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9' and python_full_version < '3.10.2'" }, { name = "packaging" }, { name = "pyproject-hooks" }, + { name = "tomli", marker = "python_full_version < '3.11.0'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/7d/46/aeab111f8e06793e4f0e421fcad593d547fb8313b50990f31681ee2fb1ad/build-1.2.2.post1.tar.gz", hash = "sha256:b36993e92ca9375a219c99e606a122ff365a760a2d4bba0caa09bd5278b608b7", size = 46701 } wheels = [ @@ -122,6 +116,7 @@ name = "celery" version = "5.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ + { name = "backports-zoneinfo", marker = "python_full_version < '3.9'" }, { name = "billiard" }, { name = "click" }, { name = "click-didyoumean" }, @@ -155,12 +150,18 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621 } wheels = [ + { url = "https://files.pythonhosted.org/packages/f8/fe/4d41c2f200c4a457933dbd98d3cf4e911870877bd94d9656cc0fcb390681/cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c", size = 171804 }, + { url = "https://files.pythonhosted.org/packages/d1/b6/0b0f5ab93b0df4acc49cae758c81fe4e5ef26c3ae2e10cc69249dfd8b3ab/cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15", size = 181299 }, { url = "https://files.pythonhosted.org/packages/34/33/e1b8a1ba29025adbdcda5fb3a36f94c03d771c1b7b12f726ff7fef2ebe36/cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655", size = 171727 }, { url = "https://files.pythonhosted.org/packages/3d/97/50228be003bb2802627d28ec0627837ac0bf35c90cf769812056f235b2d1/cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0", size = 181400 }, { url = "https://files.pythonhosted.org/packages/86/c5/28b2d6f799ec0bdecf44dced2ec5ed43e0eb63097b0f58c293583b406582/cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", size = 172448 }, { url = "https://files.pythonhosted.org/packages/50/b9/db34c4755a7bd1cb2d1603ac3863f22bcecbd1ba29e5ee841a4bc510b294/cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", size = 181976 }, { url = "https://files.pythonhosted.org/packages/bf/ee/f94057fa6426481d663b88637a9a10e859e492c73d0384514a17d78ee205/cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", size = 172475 }, { url = "https://files.pythonhosted.org/packages/7c/fc/6a8cb64e5f0324877d503c854da15d76c1e50eb722e320b15345c4d0c6de/cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", size = 182009 }, + { url = "https://files.pythonhosted.org/packages/e2/63/2bed8323890cb613bbecda807688a31ed11a7fe7afe31f8faaae0206a9a3/cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8", size = 171576 }, + { url = "https://files.pythonhosted.org/packages/2f/70/80c33b044ebc79527447fd4fbc5455d514c3bb840dede4455de97da39b4d/cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1", size = 181229 }, + { url = "https://files.pythonhosted.org/packages/cb/b5/fd9f8b5a84010ca169ee49f4e4ad6f8c05f4e3545b72ee041dbbcb159882/cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7", size = 171820 }, + { url = "https://files.pythonhosted.org/packages/8c/52/b08750ce0bce45c143e1b5d7357ee8c55341b52bdef4b0f081af1eb248c2/cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662", size = 181290 }, ] [[package]] @@ -178,7 +179,9 @@ version = "0.50" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "build" }, - { name = "setuptools" }, + { name = "setuptools", version = "75.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "setuptools", version = "75.8.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "tomli", marker = "python_full_version < '3.11.0'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/a8/ab/7607952f2c8d34c4124309dd3ea17c256fd3420a4ade01322daf9402b0b5/check_manifest-0.50.tar.gz", hash = "sha256:d300f9f292986aa1a30424af44eb45c5644e0a810e392e62d553b24bb3393494", size = 44827 } wheels = [ @@ -243,12 +246,113 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, ] +[[package]] +name = "coverage" +version = "7.6.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.9'", +] +sdist = { url = "https://files.pythonhosted.org/packages/f7/08/7e37f82e4d1aead42a7443ff06a1e406aabf7302c4f00a546e4b320b994c/coverage-7.6.1.tar.gz", hash = "sha256:953510dfb7b12ab69d20135a0662397f077c59b1e6379a768e97c59d852ee51d", size = 798791 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/61/eb7ce5ed62bacf21beca4937a90fe32545c91a3c8a42a30c6616d48fc70d/coverage-7.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b06079abebbc0e89e6163b8e8f0e16270124c154dc6e4a47b413dd538859af16", size = 206690 }, + { url = "https://files.pythonhosted.org/packages/7d/73/041928e434442bd3afde5584bdc3f932fb4562b1597629f537387cec6f3d/coverage-7.6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cf4b19715bccd7ee27b6b120e7e9dd56037b9c0681dcc1adc9ba9db3d417fa36", size = 207127 }, + { url = "https://files.pythonhosted.org/packages/c7/c8/6ca52b5147828e45ad0242388477fdb90df2c6cbb9a441701a12b3c71bc8/coverage-7.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61c0abb4c85b095a784ef23fdd4aede7a2628478e7baba7c5e3deba61070a02", size = 235654 }, + { url = "https://files.pythonhosted.org/packages/d5/da/9ac2b62557f4340270942011d6efeab9833648380109e897d48ab7c1035d/coverage-7.6.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd21f6ae3f08b41004dfb433fa895d858f3f5979e7762d052b12aef444e29afc", size = 233598 }, + { url = "https://files.pythonhosted.org/packages/53/23/9e2c114d0178abc42b6d8d5281f651a8e6519abfa0ef460a00a91f80879d/coverage-7.6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f59d57baca39b32db42b83b2a7ba6f47ad9c394ec2076b084c3f029b7afca23", size = 234732 }, + { url = "https://files.pythonhosted.org/packages/0f/7e/a0230756fb133343a52716e8b855045f13342b70e48e8ad41d8a0d60ab98/coverage-7.6.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a1ac0ae2b8bd743b88ed0502544847c3053d7171a3cff9228af618a068ed9c34", size = 233816 }, + { url = "https://files.pythonhosted.org/packages/28/7c/3753c8b40d232b1e5eeaed798c875537cf3cb183fb5041017c1fdb7ec14e/coverage-7.6.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e6a08c0be454c3b3beb105c0596ebdc2371fab6bb90c0c0297f4e58fd7e1012c", size = 232325 }, + { url = "https://files.pythonhosted.org/packages/57/e3/818a2b2af5b7573b4b82cf3e9f137ab158c90ea750a8f053716a32f20f06/coverage-7.6.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f5796e664fe802da4f57a168c85359a8fbf3eab5e55cd4e4569fbacecc903959", size = 233418 }, + { url = "https://files.pythonhosted.org/packages/c8/fb/4532b0b0cefb3f06d201648715e03b0feb822907edab3935112b61b885e2/coverage-7.6.1-cp310-cp310-win32.whl", hash = "sha256:7bb65125fcbef8d989fa1dd0e8a060999497629ca5b0efbca209588a73356232", size = 209343 }, + { url = "https://files.pythonhosted.org/packages/5a/25/af337cc7421eca1c187cc9c315f0a755d48e755d2853715bfe8c418a45fa/coverage-7.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:3115a95daa9bdba70aea750db7b96b37259a81a709223c8448fa97727d546fe0", size = 210136 }, + { url = "https://files.pythonhosted.org/packages/ad/5f/67af7d60d7e8ce61a4e2ddcd1bd5fb787180c8d0ae0fbd073f903b3dd95d/coverage-7.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7dea0889685db8550f839fa202744652e87c60015029ce3f60e006f8c4462c93", size = 206796 }, + { url = "https://files.pythonhosted.org/packages/e1/0e/e52332389e057daa2e03be1fbfef25bb4d626b37d12ed42ae6281d0a274c/coverage-7.6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed37bd3c3b063412f7620464a9ac1314d33100329f39799255fb8d3027da50d3", size = 207244 }, + { url = "https://files.pythonhosted.org/packages/aa/cd/766b45fb6e090f20f8927d9c7cb34237d41c73a939358bc881883fd3a40d/coverage-7.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d85f5e9a5f8b73e2350097c3756ef7e785f55bd71205defa0bfdaf96c31616ff", size = 239279 }, + { url = "https://files.pythonhosted.org/packages/70/6c/a9ccd6fe50ddaf13442a1e2dd519ca805cbe0f1fcd377fba6d8339b98ccb/coverage-7.6.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bc572be474cafb617672c43fe989d6e48d3c83af02ce8de73fff1c6bb3c198d", size = 236859 }, + { url = "https://files.pythonhosted.org/packages/14/6f/8351b465febb4dbc1ca9929505202db909c5a635c6fdf33e089bbc3d7d85/coverage-7.6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c0420b573964c760df9e9e86d1a9a622d0d27f417e1a949a8a66dd7bcee7bc6", size = 238549 }, + { url = "https://files.pythonhosted.org/packages/68/3c/289b81fa18ad72138e6d78c4c11a82b5378a312c0e467e2f6b495c260907/coverage-7.6.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1f4aa8219db826ce6be7099d559f8ec311549bfc4046f7f9fe9b5cea5c581c56", size = 237477 }, + { url = "https://files.pythonhosted.org/packages/ed/1c/aa1efa6459d822bd72c4abc0b9418cf268de3f60eeccd65dc4988553bd8d/coverage-7.6.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:fc5a77d0c516700ebad189b587de289a20a78324bc54baee03dd486f0855d234", size = 236134 }, + { url = "https://files.pythonhosted.org/packages/fb/c8/521c698f2d2796565fe9c789c2ee1ccdae610b3aa20b9b2ef980cc253640/coverage-7.6.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b48f312cca9621272ae49008c7f613337c53fadca647d6384cc129d2996d1133", size = 236910 }, + { url = "https://files.pythonhosted.org/packages/7d/30/033e663399ff17dca90d793ee8a2ea2890e7fdf085da58d82468b4220bf7/coverage-7.6.1-cp311-cp311-win32.whl", hash = "sha256:1125ca0e5fd475cbbba3bb67ae20bd2c23a98fac4e32412883f9bcbaa81c314c", size = 209348 }, + { url = "https://files.pythonhosted.org/packages/20/05/0d1ccbb52727ccdadaa3ff37e4d2dc1cd4d47f0c3df9eb58d9ec8508ca88/coverage-7.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:8ae539519c4c040c5ffd0632784e21b2f03fc1340752af711f33e5be83a9d6c6", size = 210230 }, + { url = "https://files.pythonhosted.org/packages/7e/d4/300fc921dff243cd518c7db3a4c614b7e4b2431b0d1145c1e274fd99bd70/coverage-7.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:95cae0efeb032af8458fc27d191f85d1717b1d4e49f7cb226cf526ff28179778", size = 206983 }, + { url = "https://files.pythonhosted.org/packages/e1/ab/6bf00de5327ecb8db205f9ae596885417a31535eeda6e7b99463108782e1/coverage-7.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5621a9175cf9d0b0c84c2ef2b12e9f5f5071357c4d2ea6ca1cf01814f45d2391", size = 207221 }, + { url = "https://files.pythonhosted.org/packages/92/8f/2ead05e735022d1a7f3a0a683ac7f737de14850395a826192f0288703472/coverage-7.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:260933720fdcd75340e7dbe9060655aff3af1f0c5d20f46b57f262ab6c86a5e8", size = 240342 }, + { url = "https://files.pythonhosted.org/packages/0f/ef/94043e478201ffa85b8ae2d2c79b4081e5a1b73438aafafccf3e9bafb6b5/coverage-7.6.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07e2ca0ad381b91350c0ed49d52699b625aab2b44b65e1b4e02fa9df0e92ad2d", size = 237371 }, + { url = "https://files.pythonhosted.org/packages/1f/0f/c890339dd605f3ebc269543247bdd43b703cce6825b5ed42ff5f2d6122c7/coverage-7.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c44fee9975f04b33331cb8eb272827111efc8930cfd582e0320613263ca849ca", size = 239455 }, + { url = "https://files.pythonhosted.org/packages/d1/04/7fd7b39ec7372a04efb0f70c70e35857a99b6a9188b5205efb4c77d6a57a/coverage-7.6.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:877abb17e6339d96bf08e7a622d05095e72b71f8afd8a9fefc82cf30ed944163", size = 238924 }, + { url = "https://files.pythonhosted.org/packages/ed/bf/73ce346a9d32a09cf369f14d2a06651329c984e106f5992c89579d25b27e/coverage-7.6.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3e0cadcf6733c09154b461f1ca72d5416635e5e4ec4e536192180d34ec160f8a", size = 237252 }, + { url = "https://files.pythonhosted.org/packages/86/74/1dc7a20969725e917b1e07fe71a955eb34bc606b938316bcc799f228374b/coverage-7.6.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c3c02d12f837d9683e5ab2f3d9844dc57655b92c74e286c262e0fc54213c216d", size = 238897 }, + { url = "https://files.pythonhosted.org/packages/b6/e9/d9cc3deceb361c491b81005c668578b0dfa51eed02cd081620e9a62f24ec/coverage-7.6.1-cp312-cp312-win32.whl", hash = "sha256:e05882b70b87a18d937ca6768ff33cc3f72847cbc4de4491c8e73880766718e5", size = 209606 }, + { url = "https://files.pythonhosted.org/packages/47/c8/5a2e41922ea6740f77d555c4d47544acd7dc3f251fe14199c09c0f5958d3/coverage-7.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:b5d7b556859dd85f3a541db6a4e0167b86e7273e1cdc973e5b175166bb634fdb", size = 210373 }, + { url = "https://files.pythonhosted.org/packages/8c/f9/9aa4dfb751cb01c949c990d136a0f92027fbcc5781c6e921df1cb1563f20/coverage-7.6.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a4acd025ecc06185ba2b801f2de85546e0b8ac787cf9d3b06e7e2a69f925b106", size = 207007 }, + { url = "https://files.pythonhosted.org/packages/b9/67/e1413d5a8591622a46dd04ff80873b04c849268831ed5c304c16433e7e30/coverage-7.6.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a6d3adcf24b624a7b778533480e32434a39ad8fa30c315208f6d3e5542aeb6e9", size = 207269 }, + { url = "https://files.pythonhosted.org/packages/14/5b/9dec847b305e44a5634d0fb8498d135ab1d88330482b74065fcec0622224/coverage-7.6.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0c212c49b6c10e6951362f7c6df3329f04c2b1c28499563d4035d964ab8e08c", size = 239886 }, + { url = "https://files.pythonhosted.org/packages/7b/b7/35760a67c168e29f454928f51f970342d23cf75a2bb0323e0f07334c85f3/coverage-7.6.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e81d7a3e58882450ec4186ca59a3f20a5d4440f25b1cff6f0902ad890e6748a", size = 237037 }, + { url = "https://files.pythonhosted.org/packages/f7/95/d2fd31f1d638df806cae59d7daea5abf2b15b5234016a5ebb502c2f3f7ee/coverage-7.6.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78b260de9790fd81e69401c2dc8b17da47c8038176a79092a89cb2b7d945d060", size = 239038 }, + { url = "https://files.pythonhosted.org/packages/6e/bd/110689ff5752b67924efd5e2aedf5190cbbe245fc81b8dec1abaffba619d/coverage-7.6.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a78d169acd38300060b28d600344a803628c3fd585c912cacc9ea8790fe96862", size = 238690 }, + { url = "https://files.pythonhosted.org/packages/d3/a8/08d7b38e6ff8df52331c83130d0ab92d9c9a8b5462f9e99c9f051a4ae206/coverage-7.6.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2c09f4ce52cb99dd7505cd0fc8e0e37c77b87f46bc9c1eb03fe3bc9991085388", size = 236765 }, + { url = "https://files.pythonhosted.org/packages/d6/6a/9cf96839d3147d55ae713eb2d877f4d777e7dc5ba2bce227167d0118dfe8/coverage-7.6.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6878ef48d4227aace338d88c48738a4258213cd7b74fd9a3d4d7582bb1d8a155", size = 238611 }, + { url = "https://files.pythonhosted.org/packages/74/e4/7ff20d6a0b59eeaab40b3140a71e38cf52547ba21dbcf1d79c5a32bba61b/coverage-7.6.1-cp313-cp313-win32.whl", hash = "sha256:44df346d5215a8c0e360307d46ffaabe0f5d3502c8a1cefd700b34baf31d411a", size = 209671 }, + { url = "https://files.pythonhosted.org/packages/35/59/1812f08a85b57c9fdb6d0b383d779e47b6f643bc278ed682859512517e83/coverage-7.6.1-cp313-cp313-win_amd64.whl", hash = "sha256:8284cf8c0dd272a247bc154eb6c95548722dce90d098c17a883ed36e67cdb129", size = 210368 }, + { url = "https://files.pythonhosted.org/packages/9c/15/08913be1c59d7562a3e39fce20661a98c0a3f59d5754312899acc6cb8a2d/coverage-7.6.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d3296782ca4eab572a1a4eca686d8bfb00226300dcefdf43faa25b5242ab8a3e", size = 207758 }, + { url = "https://files.pythonhosted.org/packages/c4/ae/b5d58dff26cade02ada6ca612a76447acd69dccdbb3a478e9e088eb3d4b9/coverage-7.6.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:502753043567491d3ff6d08629270127e0c31d4184c4c8d98f92c26f65019962", size = 208035 }, + { url = "https://files.pythonhosted.org/packages/b8/d7/62095e355ec0613b08dfb19206ce3033a0eedb6f4a67af5ed267a8800642/coverage-7.6.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a89ecca80709d4076b95f89f308544ec8f7b4727e8a547913a35f16717856cb", size = 250839 }, + { url = "https://files.pythonhosted.org/packages/7c/1e/c2967cb7991b112ba3766df0d9c21de46b476d103e32bb401b1b2adf3380/coverage-7.6.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a318d68e92e80af8b00fa99609796fdbcdfef3629c77c6283566c6f02c6d6704", size = 246569 }, + { url = "https://files.pythonhosted.org/packages/8b/61/a7a6a55dd266007ed3b1df7a3386a0d760d014542d72f7c2c6938483b7bd/coverage-7.6.1-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13b0a73a0896988f053e4fbb7de6d93388e6dd292b0d87ee51d106f2c11b465b", size = 248927 }, + { url = "https://files.pythonhosted.org/packages/c8/fa/13a6f56d72b429f56ef612eb3bc5ce1b75b7ee12864b3bd12526ab794847/coverage-7.6.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4421712dbfc5562150f7554f13dde997a2e932a6b5f352edcce948a815efee6f", size = 248401 }, + { url = "https://files.pythonhosted.org/packages/75/06/0429c652aa0fb761fc60e8c6b291338c9173c6aa0f4e40e1902345b42830/coverage-7.6.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:166811d20dfea725e2e4baa71fffd6c968a958577848d2131f39b60043400223", size = 246301 }, + { url = "https://files.pythonhosted.org/packages/52/76/1766bb8b803a88f93c3a2d07e30ffa359467810e5cbc68e375ebe6906efb/coverage-7.6.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:225667980479a17db1048cb2bf8bfb39b8e5be8f164b8f6628b64f78a72cf9d3", size = 247598 }, + { url = "https://files.pythonhosted.org/packages/66/8b/f54f8db2ae17188be9566e8166ac6df105c1c611e25da755738025708d54/coverage-7.6.1-cp313-cp313t-win32.whl", hash = "sha256:170d444ab405852903b7d04ea9ae9b98f98ab6d7e63e1115e82620807519797f", size = 210307 }, + { url = "https://files.pythonhosted.org/packages/9f/b0/e0dca6da9170aefc07515cce067b97178cefafb512d00a87a1c717d2efd5/coverage-7.6.1-cp313-cp313t-win_amd64.whl", hash = "sha256:b9f222de8cded79c49bf184bdbc06630d4c58eec9459b939b4a690c82ed05657", size = 211453 }, + { url = "https://files.pythonhosted.org/packages/81/d0/d9e3d554e38beea5a2e22178ddb16587dbcbe9a1ef3211f55733924bf7fa/coverage-7.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6db04803b6c7291985a761004e9060b2bca08da6d04f26a7f2294b8623a0c1a0", size = 206674 }, + { url = "https://files.pythonhosted.org/packages/38/ea/cab2dc248d9f45b2b7f9f1f596a4d75a435cb364437c61b51d2eb33ceb0e/coverage-7.6.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f1adfc8ac319e1a348af294106bc6a8458a0f1633cc62a1446aebc30c5fa186a", size = 207101 }, + { url = "https://files.pythonhosted.org/packages/ca/6f/f82f9a500c7c5722368978a5390c418d2a4d083ef955309a8748ecaa8920/coverage-7.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a95324a9de9650a729239daea117df21f4b9868ce32e63f8b650ebe6cef5595b", size = 236554 }, + { url = "https://files.pythonhosted.org/packages/a6/94/d3055aa33d4e7e733d8fa309d9adf147b4b06a82c1346366fc15a2b1d5fa/coverage-7.6.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b43c03669dc4618ec25270b06ecd3ee4fa94c7f9b3c14bae6571ca00ef98b0d3", size = 234440 }, + { url = "https://files.pythonhosted.org/packages/e4/6e/885bcd787d9dd674de4a7d8ec83faf729534c63d05d51d45d4fa168f7102/coverage-7.6.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8929543a7192c13d177b770008bc4e8119f2e1f881d563fc6b6305d2d0ebe9de", size = 235889 }, + { url = "https://files.pythonhosted.org/packages/f4/63/df50120a7744492710854860783d6819ff23e482dee15462c9a833cc428a/coverage-7.6.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:a09ece4a69cf399510c8ab25e0950d9cf2b42f7b3cb0374f95d2e2ff594478a6", size = 235142 }, + { url = "https://files.pythonhosted.org/packages/3a/5d/9d0acfcded2b3e9ce1c7923ca52ccc00c78a74e112fc2aee661125b7843b/coverage-7.6.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:9054a0754de38d9dbd01a46621636689124d666bad1936d76c0341f7d71bf569", size = 233805 }, + { url = "https://files.pythonhosted.org/packages/c4/56/50abf070cb3cd9b1dd32f2c88f083aab561ecbffbcd783275cb51c17f11d/coverage-7.6.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0dbde0f4aa9a16fa4d754356a8f2e36296ff4d83994b2c9d8398aa32f222f989", size = 234655 }, + { url = "https://files.pythonhosted.org/packages/25/ee/b4c246048b8485f85a2426ef4abab88e48c6e80c74e964bea5cd4cd4b115/coverage-7.6.1-cp38-cp38-win32.whl", hash = "sha256:da511e6ad4f7323ee5702e6633085fb76c2f893aaf8ce4c51a0ba4fc07580ea7", size = 209296 }, + { url = "https://files.pythonhosted.org/packages/5c/1c/96cf86b70b69ea2b12924cdf7cabb8ad10e6130eab8d767a1099fbd2a44f/coverage-7.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:3f1156e3e8f2872197af3840d8ad307a9dd18e615dc64d9ee41696f287c57ad8", size = 210137 }, + { url = "https://files.pythonhosted.org/packages/19/d3/d54c5aa83268779d54c86deb39c1c4566e5d45c155369ca152765f8db413/coverage-7.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:abd5fd0db5f4dc9289408aaf34908072f805ff7792632250dcb36dc591d24255", size = 206688 }, + { url = "https://files.pythonhosted.org/packages/a5/fe/137d5dca72e4a258b1bc17bb04f2e0196898fe495843402ce826a7419fe3/coverage-7.6.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:547f45fa1a93154bd82050a7f3cddbc1a7a4dd2a9bf5cb7d06f4ae29fe94eaf8", size = 207120 }, + { url = "https://files.pythonhosted.org/packages/78/5b/a0a796983f3201ff5485323b225d7c8b74ce30c11f456017e23d8e8d1945/coverage-7.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:645786266c8f18a931b65bfcefdbf6952dd0dea98feee39bd188607a9d307ed2", size = 235249 }, + { url = "https://files.pythonhosted.org/packages/4e/e1/76089d6a5ef9d68f018f65411fcdaaeb0141b504587b901d74e8587606ad/coverage-7.6.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e0b2df163b8ed01d515807af24f63de04bebcecbd6c3bfeff88385789fdf75a", size = 233237 }, + { url = "https://files.pythonhosted.org/packages/9a/6f/eef79b779a540326fee9520e5542a8b428cc3bfa8b7c8f1022c1ee4fc66c/coverage-7.6.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:609b06f178fe8e9f89ef676532760ec0b4deea15e9969bf754b37f7c40326dbc", size = 234311 }, + { url = "https://files.pythonhosted.org/packages/75/e1/656d65fb126c29a494ef964005702b012f3498db1a30dd562958e85a4049/coverage-7.6.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:702855feff378050ae4f741045e19a32d57d19f3e0676d589df0575008ea5004", size = 233453 }, + { url = "https://files.pythonhosted.org/packages/68/6a/45f108f137941a4a1238c85f28fd9d048cc46b5466d6b8dda3aba1bb9d4f/coverage-7.6.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:2bdb062ea438f22d99cba0d7829c2ef0af1d768d1e4a4f528087224c90b132cb", size = 231958 }, + { url = "https://files.pythonhosted.org/packages/9b/e7/47b809099168b8b8c72ae311efc3e88c8d8a1162b3ba4b8da3cfcdb85743/coverage-7.6.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9c56863d44bd1c4fe2abb8a4d6f5371d197f1ac0ebdee542f07f35895fc07f36", size = 232938 }, + { url = "https://files.pythonhosted.org/packages/52/80/052222ba7058071f905435bad0ba392cc12006380731c37afaf3fe749b88/coverage-7.6.1-cp39-cp39-win32.whl", hash = "sha256:6e2cd258d7d927d09493c8df1ce9174ad01b381d4729a9d8d4e38670ca24774c", size = 209352 }, + { url = "https://files.pythonhosted.org/packages/b8/d8/1b92e0b3adcf384e98770a00ca095da1b5f7b483e6563ae4eb5e935d24a1/coverage-7.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:06a737c882bd26d0d6ee7269b20b12f14a8704807a01056c80bb881a4b2ce6ca", size = 210153 }, + { url = "https://files.pythonhosted.org/packages/a5/2b/0354ed096bca64dc8e32a7cbcae28b34cb5ad0b1fe2125d6d99583313ac0/coverage-7.6.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:e9a6e0eb86070e8ccaedfbd9d38fec54864f3125ab95419970575b42af7541df", size = 198926 }, +] + +[package.optional-dependencies] +toml = [ + { name = "tomli", marker = "python_full_version < '3.9'" }, +] + [[package]] name = "coverage" version = "7.6.10" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.13'", + "python_full_version >= '3.9' and python_full_version < '3.13'", +] sdist = { url = "https://files.pythonhosted.org/packages/84/ba/ac14d281f80aab516275012e8875991bb06203957aa1e19950139238d658/coverage-7.6.10.tar.gz", hash = "sha256:7fb105327c8f8f0682e29843e2ff96af9dcbe5bab8eeb4b398c6a33a16d80a23", size = 803868 } wheels = [ + { url = "https://files.pythonhosted.org/packages/c5/12/2a2a923edf4ddabdffed7ad6da50d96a5c126dae7b80a33df7310e329a1e/coverage-7.6.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5c912978f7fbf47ef99cec50c4401340436d200d41d714c7a4766f377c5b7b78", size = 207982 }, + { url = "https://files.pythonhosted.org/packages/ca/49/6985dbca9c7be3f3cb62a2e6e492a0c88b65bf40579e16c71ae9c33c6b23/coverage-7.6.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a01ec4af7dfeb96ff0078ad9a48810bb0cc8abcb0115180c6013a6b26237626c", size = 208414 }, + { url = "https://files.pythonhosted.org/packages/35/93/287e8f1d1ed2646f4e0b2605d14616c9a8a2697d0d1b453815eb5c6cebdb/coverage-7.6.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3b204c11e2b2d883946fe1d97f89403aa1811df28ce0447439178cc7463448a", size = 236860 }, + { url = "https://files.pythonhosted.org/packages/de/e1/cfdb5627a03567a10031acc629b75d45a4ca1616e54f7133ca1fa366050a/coverage-7.6.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32ee6d8491fcfc82652a37109f69dee9a830e9379166cb73c16d8dc5c2915165", size = 234758 }, + { url = "https://files.pythonhosted.org/packages/6d/85/fc0de2bcda3f97c2ee9fe8568f7d48f7279e91068958e5b2cc19e0e5f600/coverage-7.6.10-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675cefc4c06e3b4c876b85bfb7c59c5e2218167bbd4da5075cbe3b5790a28988", size = 235920 }, + { url = "https://files.pythonhosted.org/packages/79/73/ef4ea0105531506a6f4cf4ba571a214b14a884630b567ed65b3d9c1975e1/coverage-7.6.10-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f4f620668dbc6f5e909a0946a877310fb3d57aea8198bde792aae369ee1c23b5", size = 234986 }, + { url = "https://files.pythonhosted.org/packages/c6/4d/75afcfe4432e2ad0405c6f27adeb109ff8976c5e636af8604f94f29fa3fc/coverage-7.6.10-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:4eea95ef275de7abaef630c9b2c002ffbc01918b726a39f5a4353916ec72d2f3", size = 233446 }, + { url = "https://files.pythonhosted.org/packages/86/5b/efee56a89c16171288cafff022e8af44f8f94075c2d8da563c3935212871/coverage-7.6.10-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e2f0280519e42b0a17550072861e0bc8a80a0870de260f9796157d3fca2733c5", size = 234566 }, + { url = "https://files.pythonhosted.org/packages/f2/db/67770cceb4a64d3198bf2aa49946f411b85ec6b0a9b489e61c8467a4253b/coverage-7.6.10-cp310-cp310-win32.whl", hash = "sha256:bc67deb76bc3717f22e765ab3e07ee9c7a5e26b9019ca19a3b063d9f4b874244", size = 210675 }, + { url = "https://files.pythonhosted.org/packages/8d/27/e8bfc43f5345ec2c27bc8a1fa77cdc5ce9dcf954445e11f14bb70b889d14/coverage-7.6.10-cp310-cp310-win_amd64.whl", hash = "sha256:0f460286cb94036455e703c66988851d970fdfd8acc2a1122ab7f4f904e4029e", size = 211518 }, { url = "https://files.pythonhosted.org/packages/85/d2/5e175fcf6766cf7501a8541d81778fd2f52f4870100e791f5327fd23270b/coverage-7.6.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ea3c8f04b3e4af80e17bab607c386a830ffc2fb88a5484e1df756478cf70d1d3", size = 208088 }, { url = "https://files.pythonhosted.org/packages/4b/6f/06db4dc8fca33c13b673986e20e466fd936235a6ec1f0045c3853ac1b593/coverage-7.6.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:507a20fc863cae1d5720797761b42d2d87a04b3e5aeb682ef3b7332e90598f43", size = 208536 }, { url = "https://files.pythonhosted.org/packages/0d/62/c6a0cf80318c1c1af376d52df444da3608eafc913b82c84a4600d8349472/coverage-7.6.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d37a84878285b903c0fe21ac8794c6dab58150e9359f1aaebbeddd6412d53132", size = 240474 }, @@ -289,11 +393,22 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/50/69/b3f2416725621e9f112e74e8470793d5b5995f146f596f133678a633b77e/coverage-7.6.10-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6f93531882a5f68c28090f901b1d135de61b56331bba82028489bc51bdd818d2", size = 248737 }, { url = "https://files.pythonhosted.org/packages/3c/6e/fe899fb937657db6df31cc3e61c6968cb56d36d7326361847440a430152e/coverage-7.6.10-cp313-cp313t-win32.whl", hash = "sha256:89d76815a26197c858f53c7f6a656686ec392b25991f9e409bcef020cd532312", size = 211611 }, { url = "https://files.pythonhosted.org/packages/1c/55/52f5e66142a9d7bc93a15192eba7a78513d2abf6b3558d77b4ca32f5f424/coverage-7.6.10-cp313-cp313t-win_amd64.whl", hash = "sha256:54a5f0f43950a36312155dae55c505a76cd7f2b12d26abeebbe7a0b36dbc868d", size = 212781 }, + { url = "https://files.pythonhosted.org/packages/40/41/473617aadf9a1c15bc2d56be65d90d7c29bfa50a957a67ef96462f7ebf8e/coverage-7.6.10-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:656c82b8a0ead8bba147de9a89bda95064874c91a3ed43a00e687f23cc19d53a", size = 207978 }, + { url = "https://files.pythonhosted.org/packages/10/f6/480586607768b39a30e6910a3c4522139094ac0f1677028e1f4823688957/coverage-7.6.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ccc2b70a7ed475c68ceb548bf69cec1e27305c1c2606a5eb7c3afff56a1b3b27", size = 208415 }, + { url = "https://files.pythonhosted.org/packages/f1/af/439bb760f817deff6f4d38fe7da08d9dd7874a560241f1945bc3b4446550/coverage-7.6.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5e37dc41d57ceba70956fa2fc5b63c26dba863c946ace9705f8eca99daecdc4", size = 236452 }, + { url = "https://files.pythonhosted.org/packages/d0/13/481f4ceffcabe29ee2332e60efb52e4694f54a402f3ada2bcec10bb32e43/coverage-7.6.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0aa9692b4fdd83a4647eeb7db46410ea1322b5ed94cd1715ef09d1d5922ba87f", size = 234374 }, + { url = "https://files.pythonhosted.org/packages/c5/59/4607ea9d6b1b73e905c7656da08d0b00cdf6e59f2293ec259e8914160025/coverage-7.6.10-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa744da1820678b475e4ba3dfd994c321c5b13381d1041fe9c608620e6676e25", size = 235505 }, + { url = "https://files.pythonhosted.org/packages/85/60/d66365723b9b7f29464b11d024248ed3523ce5aab958e4ad8c43f3f4148b/coverage-7.6.10-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c0b1818063dc9e9d838c09e3a473c1422f517889436dd980f5d721899e66f315", size = 234616 }, + { url = "https://files.pythonhosted.org/packages/74/f8/2cf7a38e7d81b266f47dfcf137fecd8fa66c7bdbd4228d611628d8ca3437/coverage-7.6.10-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:59af35558ba08b758aec4d56182b222976330ef8d2feacbb93964f576a7e7a90", size = 233099 }, + { url = "https://files.pythonhosted.org/packages/50/2b/bff6c1c6b63c4396ea7ecdbf8db1788b46046c681b8fcc6ec77db9f4ea49/coverage-7.6.10-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7ed2f37cfce1ce101e6dffdfd1c99e729dd2ffc291d02d3e2d0af8b53d13840d", size = 234089 }, + { url = "https://files.pythonhosted.org/packages/bf/b5/baace1c754d546a67779358341aa8d2f7118baf58cac235db457e1001d1b/coverage-7.6.10-cp39-cp39-win32.whl", hash = "sha256:4bcc276261505d82f0ad426870c3b12cb177752834a633e737ec5ee79bbdff18", size = 210701 }, + { url = "https://files.pythonhosted.org/packages/b1/bf/9e1e95b8b20817398ecc5a1e8d3e05ff404e1b9fb2185cd71561698fe2a2/coverage-7.6.10-cp39-cp39-win_amd64.whl", hash = "sha256:457574f4599d2b00f7f637a0700a6422243b3565509457b2dbd3f50703e11f59", size = 211482 }, + { url = "https://files.pythonhosted.org/packages/a1/70/de81bfec9ed38a64fc44a77c7665e20ca507fc3265597c28b0d989e4082e/coverage-7.6.10-pp39.pp310-none-any.whl", hash = "sha256:fd34e7b3405f0cc7ab03d54a334c17a9e802897580d964bd8c2001f4b9fd488f", size = 200223 }, ] [package.optional-dependencies] toml = [ - { name = "tomli", marker = "python_full_version <= '3.11'" }, + { name = "tomli", marker = "python_full_version >= '3.9' and python_full_version <= '3.11'" }, ] [[package]] @@ -323,28 +438,34 @@ dependencies = [ [package.dev-dependencies] dev = [ - { name = "black" }, { name = "celery" }, { name = "check-manifest" }, { name = "django-admin-extra-urls" }, { name = "django-dynamic-fixture" }, - { name = "django-environ" }, + { name = "django-environ", version = "0.11.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "django-environ", version = "0.12.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, { name = "django-webtest" }, { name = "mock" }, { name = "modernize" }, - { name = "mypy" }, - { name = "pillow" }, + { name = "mypy", version = "1.14.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "mypy", version = "1.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "pillow", version = "10.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "pillow", version = "11.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, { name = "psycopg2" }, { name = "pytest" }, { name = "pytest-cache" }, - { name = "pytest-cov" }, + { name = "pytest-cov", version = "5.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "pytest-cov", version = "6.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, { name = "pytest-django" }, - { name = "pytest-echo" }, + { name = "pytest-echo", version = "1.7.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "pytest-echo", version = "1.8.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, { name = "readme" }, { name = "redis" }, { name = "ruff" }, - { name = "selenium" }, - { name = "setuptools" }, + { name = "selenium", version = "4.27.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "selenium", version = "4.28.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "setuptools", version = "75.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "setuptools", version = "75.8.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, { name = "tox" }, ] @@ -357,23 +478,22 @@ requires-dist = [ [package.metadata.requires-dev] dev = [ - { name = "black", specifier = ">=25.1" }, - { name = "celery", specifier = ">=5.4" }, - { name = "check-manifest", specifier = ">=0.50" }, - { name = "django-admin-extra-urls", specifier = ">=4.1.1" }, - { name = "django-dynamic-fixture", specifier = ">=4.0.1" }, - { name = "django-environ", specifier = ">=0.12" }, - { name = "django-webtest", specifier = ">1.9.6" }, - { name = "mock", specifier = ">=1.0.1" }, - { name = "modernize", specifier = ">=0.8" }, - { name = "mypy", specifier = ">=1.15" }, - { name = "pillow", specifier = ">=11.1" }, - { name = "psycopg2", specifier = ">=2.9.10" }, - { name = "pytest", specifier = ">=8.3.4" }, - { name = "pytest-cache", specifier = ">=1" }, - { name = "pytest-cov", specifier = ">=6" }, - { name = "pytest-django", specifier = ">=4.9" }, - { name = "pytest-echo", specifier = ">=1.8.1" }, + { name = "celery" }, + { name = "check-manifest" }, + { name = "django-admin-extra-urls" }, + { name = "django-dynamic-fixture" }, + { name = "django-environ" }, + { name = "django-webtest" }, + { name = "mock" }, + { name = "modernize" }, + { name = "mypy" }, + { name = "pillow" }, + { name = "psycopg2" }, + { name = "pytest" }, + { name = "pytest-cache" }, + { name = "pytest-cov" }, + { name = "pytest-django" }, + { name = "pytest-echo" }, { name = "readme", specifier = ">=0.7.1" }, { name = "redis", specifier = ">=5.2.1" }, { name = "ruff", specifier = ">=0.9.4" }, @@ -391,10 +511,26 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5f/ca/f77782903f93a4ba42204dce89682c5de734d88002cefa6071f805697620/django_dynamic_fixture-4.0.1-py3-none-any.whl", hash = "sha256:d0611b6dc594fb1bccad1fd94dade89cc8deca12385bc2763baded3e48322547", size = 58712 }, ] +[[package]] +name = "django-environ" +version = "0.11.2" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.9'", +] +sdist = { url = "https://files.pythonhosted.org/packages/d6/0b/f2c024529ee4bbf8b95176eebeb86c6e695192a9ce0e91059cb83a33c1d3/django-environ-0.11.2.tar.gz", hash = "sha256:f32a87aa0899894c27d4e1776fa6b477e8164ed7f6b3e410a62a6d72caaf64be", size = 54326 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c4/f1/468b49cccba3b42dda571063a14c668bb0b53a1d5712426d18e36663bd53/django_environ-0.11.2-py2.py3-none-any.whl", hash = "sha256:0ff95ab4344bfeff693836aa978e6840abef2e2f1145adff7735892711590c05", size = 19141 }, +] + [[package]] name = "django-environ" version = "0.12.0" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.13'", + "python_full_version >= '3.9' and python_full_version < '3.13'", +] sdist = { url = "https://files.pythonhosted.org/packages/d6/04/65d2521842c42f4716225f20d8443a50804920606aec018188bbee30a6b0/django_environ-0.12.0.tar.gz", hash = "sha256:227dc891453dd5bde769c3449cf4a74b6f2ee8f7ab2361c93a07068f4179041a", size = 56804 } wheels = [ { url = "https://files.pythonhosted.org/packages/83/b3/0a3bec4ecbfee960f39b1842c2f91e4754251e0a6ed443db9fe3f666ba8f/django_environ-0.12.0-py2.py3-none-any.whl", hash = "sha256:92fb346a158abda07ffe6eb23135ce92843af06ecf8753f43adf9d2366dcc0ca", size = 19957 }, @@ -405,22 +541,48 @@ name = "django-webtest" version = "1.9.12" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "webtest" }, + { name = "webtest", version = "3.0.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "webtest", version = "3.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/47/e3/e087630e62bcf29ed1c3560ae98b12c45e0ac07b4899ab3b8ef6a1967dde/django_webtest-1.9.12.tar.gz", hash = "sha256:5012c30665e7a6e585a1544eda75045d07d5b3f5ccccd4d0fe144c4555884095", size = 28848 } wheels = [ { url = "https://files.pythonhosted.org/packages/97/0b/c7e6c3a59ea001ca51a966477eafd2746e63b6ff2fce7dcf3c3b3c0ad765/django_webtest-1.9.12-py3-none-any.whl", hash = "sha256:de5c988c20eef7abbb3d0508494d9e576af08087d0fb6109b1d54f15ef4d78fa", size = 16583 }, ] +[[package]] +name = "docutils" +version = "0.20.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.9'", +] +sdist = { url = "https://files.pythonhosted.org/packages/1f/53/a5da4f2c5739cf66290fac1431ee52aff6851c7c8ffd8264f13affd7bcdd/docutils-0.20.1.tar.gz", hash = "sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b", size = 2058365 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/26/87/f238c0670b94533ac0353a4e2a1a771a0cc73277b88bff23d3ae35a256c1/docutils-0.20.1-py3-none-any.whl", hash = "sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6", size = 572666 }, +] + [[package]] name = "docutils" version = "0.21.2" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.13'", + "python_full_version >= '3.9' and python_full_version < '3.13'", +] sdist = { url = "https://files.pythonhosted.org/packages/ae/ed/aefcc8cd0ba62a0560c3c18c33925362d46c6075480bfa4df87b28e169a9/docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f", size = 2204444 } wheels = [ { url = "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2", size = 587408 }, ] +[[package]] +name = "exceptiongroup" +version = "1.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/09/35/2495c4ac46b980e4ca1f6ad6db102322ef3ad2410b79fdde159a4b0f3b92/exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc", size = 28883 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/02/cc/b7e31358aac6ed1ef2bb790a9746ac2c69bcb3c8588b41616914eb106eaf/exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b", size = 16453 }, +] + [[package]] name = "execnet" version = "2.1.1" @@ -430,10 +592,26 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/43/09/2aea36ff60d16dd8879bdb2f5b3ee0ba8d08cbbdcdfe870e695ce3784385/execnet-2.1.1-py3-none-any.whl", hash = "sha256:26dee51f1b80cebd6d0ca8e74dd8745419761d3bef34163928cbebbdc4749fdc", size = 40612 }, ] +[[package]] +name = "filelock" +version = "3.16.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.9'", +] +sdist = { url = "https://files.pythonhosted.org/packages/9d/db/3ef5bb276dae18d6ec2124224403d1d67bccdbefc17af4cc8f553e341ab1/filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435", size = 18037 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b9/f8/feced7779d755758a52d1f6635d990b8d98dc0a29fa568bbe0625f18fdf3/filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0", size = 16163 }, +] + [[package]] name = "filelock" version = "3.17.0" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.13'", + "python_full_version >= '3.9' and python_full_version < '3.13'", +] sdist = { url = "https://files.pythonhosted.org/packages/dc/9c/0b15fb47b464e1b663b1acd1253a062aa5feecb07d4e597daea542ebd2b5/filelock-3.17.0.tar.gz", hash = "sha256:ee4e77401ef576ebb38cd7f13b9b28893194acc20a8e68e18730ba9c0e54660e", size = 18027 } wheels = [ { url = "https://files.pythonhosted.org/packages/89/ec/00d68c4ddfedfe64159999e5f8a98fb8442729a63e2077eb9dcd89623d27/filelock-3.17.0-py3-none-any.whl", hash = "sha256:533dc2f7ba78dc2f0f531fc6c4940addf7b70a481e269a5a3b93be94ffbe8338", size = 16164 }, @@ -469,6 +647,36 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 }, ] +[[package]] +name = "importlib-metadata" +version = "8.5.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.9'", +] +dependencies = [ + { name = "zipp", version = "3.20.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cd/12/33e59336dca5be0c398a7482335911a33aa0e20776128f038019f1a95f1b/importlib_metadata-8.5.0.tar.gz", hash = "sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7", size = 55304 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/d9/a1e041c5e7caa9a05c925f4bdbdfb7f006d1f74996af53467bc394c97be7/importlib_metadata-8.5.0-py3-none-any.whl", hash = "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b", size = 26514 }, +] + +[[package]] +name = "importlib-metadata" +version = "8.6.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.9' and python_full_version < '3.13'", +] +dependencies = [ + { name = "zipp", version = "3.21.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/33/08/c1395a292bb23fd03bdf572a1357c5a733d3eecbab877641ceacab23db6e/importlib_metadata-8.6.1.tar.gz", hash = "sha256:310b41d755445d74569f993ccfc22838295d9fe005425094fad953d7f15c8580", size = 55767 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/79/9d/0fb148dc4d6fa4a7dd1d8378168d9b4cd8d4560a6fbf6f0121c5fc34eb68/importlib_metadata-8.6.1-py3-none-any.whl", hash = "sha256:02a89390c1e15fdfdc0d7c6b25cb3e62650d0494005c97d6f148bf5b9787525e", size = 26971 }, +] + [[package]] name = "iniconfig" version = "2.0.0" @@ -484,7 +692,9 @@ version = "5.4.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "amqp" }, - { name = "tzdata" }, + { name = "backports-zoneinfo", extra = ["tzdata"], marker = "python_full_version < '3.9'" }, + { name = "typing-extensions", marker = "python_full_version < '3.10'" }, + { name = "tzdata", marker = "python_full_version >= '3.9'" }, { name = "vine" }, ] sdist = { url = "https://files.pythonhosted.org/packages/38/4d/b93fcb353d279839cc35d0012bee805ed0cf61c07587916bfc35dbfddaf1/kombu-5.4.2.tar.gz", hash = "sha256:eef572dd2fd9fc614b37580e3caeafdd5af46c1eff31e7fba89138cdb406f2cf", size = 442858 } @@ -522,16 +732,80 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/73/6d/c381a4b811a3c529626268276512d1b5abef601e45bc04f0e797284b49bc/modernize-0.8.0-py2.py3-none-any.whl", hash = "sha256:b51f930ac9d726903f2c7f9038146d6061a14509140d6e4498827b19b5610120", size = 27243 }, ] +[[package]] +name = "mypy" +version = "1.14.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.9'", +] +dependencies = [ + { name = "mypy-extensions", marker = "python_full_version < '3.9'" }, + { name = "tomli", marker = "python_full_version < '3.9'" }, + { name = "typing-extensions", marker = "python_full_version < '3.9'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b9/eb/2c92d8ea1e684440f54fa49ac5d9a5f19967b7b472a281f419e69a8d228e/mypy-1.14.1.tar.gz", hash = "sha256:7ec88144fe9b510e8475ec2f5f251992690fcf89ccb4500b214b4226abcd32d6", size = 3216051 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/7a/87ae2adb31d68402da6da1e5f30c07ea6063e9f09b5e7cfc9dfa44075e74/mypy-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:52686e37cf13d559f668aa398dd7ddf1f92c5d613e4f8cb262be2fb4fedb0fcb", size = 11211002 }, + { url = "https://files.pythonhosted.org/packages/e1/23/eada4c38608b444618a132be0d199b280049ded278b24cbb9d3fc59658e4/mypy-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1fb545ca340537d4b45d3eecdb3def05e913299ca72c290326be19b3804b39c0", size = 10358400 }, + { url = "https://files.pythonhosted.org/packages/43/c9/d6785c6f66241c62fd2992b05057f404237deaad1566545e9f144ced07f5/mypy-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:90716d8b2d1f4cd503309788e51366f07c56635a3309b0f6a32547eaaa36a64d", size = 12095172 }, + { url = "https://files.pythonhosted.org/packages/c3/62/daa7e787770c83c52ce2aaf1a111eae5893de9e004743f51bfcad9e487ec/mypy-1.14.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ae753f5c9fef278bcf12e1a564351764f2a6da579d4a81347e1d5a15819997b", size = 12828732 }, + { url = "https://files.pythonhosted.org/packages/1b/a2/5fb18318a3637f29f16f4e41340b795da14f4751ef4f51c99ff39ab62e52/mypy-1.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e0fe0f5feaafcb04505bcf439e991c6d8f1bf8b15f12b05feeed96e9e7bf1427", size = 13012197 }, + { url = "https://files.pythonhosted.org/packages/28/99/e153ce39105d164b5f02c06c35c7ba958aaff50a2babba7d080988b03fe7/mypy-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:7d54bd85b925e501c555a3227f3ec0cfc54ee8b6930bd6141ec872d1c572f81f", size = 9780836 }, + { url = "https://files.pythonhosted.org/packages/da/11/a9422850fd506edbcdc7f6090682ecceaf1f87b9dd847f9df79942da8506/mypy-1.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f995e511de847791c3b11ed90084a7a0aafdc074ab88c5a9711622fe4751138c", size = 11120432 }, + { url = "https://files.pythonhosted.org/packages/b6/9e/47e450fd39078d9c02d620545b2cb37993a8a8bdf7db3652ace2f80521ca/mypy-1.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d64169ec3b8461311f8ce2fd2eb5d33e2d0f2c7b49116259c51d0d96edee48d1", size = 10279515 }, + { url = "https://files.pythonhosted.org/packages/01/b5/6c8d33bd0f851a7692a8bfe4ee75eb82b6983a3cf39e5e32a5d2a723f0c1/mypy-1.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba24549de7b89b6381b91fbc068d798192b1b5201987070319889e93038967a8", size = 12025791 }, + { url = "https://files.pythonhosted.org/packages/f0/4c/e10e2c46ea37cab5c471d0ddaaa9a434dc1d28650078ac1b56c2d7b9b2e4/mypy-1.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:183cf0a45457d28ff9d758730cd0210419ac27d4d3f285beda038c9083363b1f", size = 12749203 }, + { url = "https://files.pythonhosted.org/packages/88/55/beacb0c69beab2153a0f57671ec07861d27d735a0faff135a494cd4f5020/mypy-1.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f2a0ecc86378f45347f586e4163d1769dd81c5a223d577fe351f26b179e148b1", size = 12885900 }, + { url = "https://files.pythonhosted.org/packages/a2/75/8c93ff7f315c4d086a2dfcde02f713004357d70a163eddb6c56a6a5eff40/mypy-1.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:ad3301ebebec9e8ee7135d8e3109ca76c23752bac1e717bc84cd3836b4bf3eae", size = 9777869 }, + { url = "https://files.pythonhosted.org/packages/43/1b/b38c079609bb4627905b74fc6a49849835acf68547ac33d8ceb707de5f52/mypy-1.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:30ff5ef8519bbc2e18b3b54521ec319513a26f1bba19a7582e7b1f58a6e69f14", size = 11266668 }, + { url = "https://files.pythonhosted.org/packages/6b/75/2ed0d2964c1ffc9971c729f7a544e9cd34b2cdabbe2d11afd148d7838aa2/mypy-1.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cb9f255c18052343c70234907e2e532bc7e55a62565d64536dbc7706a20b78b9", size = 10254060 }, + { url = "https://files.pythonhosted.org/packages/a1/5f/7b8051552d4da3c51bbe8fcafffd76a6823779101a2b198d80886cd8f08e/mypy-1.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b4e3413e0bddea671012b063e27591b953d653209e7a4fa5e48759cda77ca11", size = 11933167 }, + { url = "https://files.pythonhosted.org/packages/04/90/f53971d3ac39d8b68bbaab9a4c6c58c8caa4d5fd3d587d16f5927eeeabe1/mypy-1.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:553c293b1fbdebb6c3c4030589dab9fafb6dfa768995a453d8a5d3b23784af2e", size = 12864341 }, + { url = "https://files.pythonhosted.org/packages/03/d2/8bc0aeaaf2e88c977db41583559319f1821c069e943ada2701e86d0430b7/mypy-1.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fad79bfe3b65fe6a1efaed97b445c3d37f7be9fdc348bdb2d7cac75579607c89", size = 12972991 }, + { url = "https://files.pythonhosted.org/packages/6f/17/07815114b903b49b0f2cf7499f1c130e5aa459411596668267535fe9243c/mypy-1.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:8fa2220e54d2946e94ab6dbb3ba0a992795bd68b16dc852db33028df2b00191b", size = 9879016 }, + { url = "https://files.pythonhosted.org/packages/9e/15/bb6a686901f59222275ab228453de741185f9d54fecbaacec041679496c6/mypy-1.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:92c3ed5afb06c3a8e188cb5da4984cab9ec9a77ba956ee419c68a388b4595255", size = 11252097 }, + { url = "https://files.pythonhosted.org/packages/f8/b3/8b0f74dfd072c802b7fa368829defdf3ee1566ba74c32a2cb2403f68024c/mypy-1.14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dbec574648b3e25f43d23577309b16534431db4ddc09fda50841f1e34e64ed34", size = 10239728 }, + { url = "https://files.pythonhosted.org/packages/c5/9b/4fd95ab20c52bb5b8c03cc49169be5905d931de17edfe4d9d2986800b52e/mypy-1.14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8c6d94b16d62eb3e947281aa7347d78236688e21081f11de976376cf010eb31a", size = 11924965 }, + { url = "https://files.pythonhosted.org/packages/56/9d/4a236b9c57f5d8f08ed346914b3f091a62dd7e19336b2b2a0d85485f82ff/mypy-1.14.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d4b19b03fdf54f3c5b2fa474c56b4c13c9dbfb9a2db4370ede7ec11a2c5927d9", size = 12867660 }, + { url = "https://files.pythonhosted.org/packages/40/88/a61a5497e2f68d9027de2bb139c7bb9abaeb1be1584649fa9d807f80a338/mypy-1.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0c911fde686394753fff899c409fd4e16e9b294c24bfd5e1ea4675deae1ac6fd", size = 12969198 }, + { url = "https://files.pythonhosted.org/packages/54/da/3d6fc5d92d324701b0c23fb413c853892bfe0e1dbe06c9138037d459756b/mypy-1.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:8b21525cb51671219f5307be85f7e646a153e5acc656e5cebf64bfa076c50107", size = 9885276 }, + { url = "https://files.pythonhosted.org/packages/39/02/1817328c1372be57c16148ce7d2bfcfa4a796bedaed897381b1aad9b267c/mypy-1.14.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7084fb8f1128c76cd9cf68fe5971b37072598e7c31b2f9f95586b65c741a9d31", size = 11143050 }, + { url = "https://files.pythonhosted.org/packages/b9/07/99db9a95ece5e58eee1dd87ca456a7e7b5ced6798fd78182c59c35a7587b/mypy-1.14.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8f845a00b4f420f693f870eaee5f3e2692fa84cc8514496114649cfa8fd5e2c6", size = 10321087 }, + { url = "https://files.pythonhosted.org/packages/9a/eb/85ea6086227b84bce79b3baf7f465b4732e0785830726ce4a51528173b71/mypy-1.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:44bf464499f0e3a2d14d58b54674dee25c031703b2ffc35064bd0df2e0fac319", size = 12066766 }, + { url = "https://files.pythonhosted.org/packages/4b/bb/f01bebf76811475d66359c259eabe40766d2f8ac8b8250d4e224bb6df379/mypy-1.14.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c99f27732c0b7dc847adb21c9d47ce57eb48fa33a17bc6d7d5c5e9f9e7ae5bac", size = 12787111 }, + { url = "https://files.pythonhosted.org/packages/2f/c9/84837ff891edcb6dcc3c27d85ea52aab0c4a34740ff5f0ccc0eb87c56139/mypy-1.14.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:bce23c7377b43602baa0bd22ea3265c49b9ff0b76eb315d6c34721af4cdf1d9b", size = 12974331 }, + { url = "https://files.pythonhosted.org/packages/84/5f/901e18464e6a13f8949b4909535be3fa7f823291b8ab4e4b36cfe57d6769/mypy-1.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:8edc07eeade7ebc771ff9cf6b211b9a7d93687ff892150cb5692e4f4272b0837", size = 9763210 }, + { url = "https://files.pythonhosted.org/packages/ca/1f/186d133ae2514633f8558e78cd658070ba686c0e9275c5a5c24a1e1f0d67/mypy-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3888a1816d69f7ab92092f785a462944b3ca16d7c470d564165fe703b0970c35", size = 11200493 }, + { url = "https://files.pythonhosted.org/packages/af/fc/4842485d034e38a4646cccd1369f6b1ccd7bc86989c52770d75d719a9941/mypy-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:46c756a444117c43ee984bd055db99e498bc613a70bbbc120272bd13ca579fbc", size = 10357702 }, + { url = "https://files.pythonhosted.org/packages/b4/e6/457b83f2d701e23869cfec013a48a12638f75b9d37612a9ddf99072c1051/mypy-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:27fc248022907e72abfd8e22ab1f10e903915ff69961174784a3900a8cba9ad9", size = 12091104 }, + { url = "https://files.pythonhosted.org/packages/f1/bf/76a569158db678fee59f4fd30b8e7a0d75bcbaeef49edd882a0d63af6d66/mypy-1.14.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:499d6a72fb7e5de92218db961f1a66d5f11783f9ae549d214617edab5d4dbdbb", size = 12830167 }, + { url = "https://files.pythonhosted.org/packages/43/bc/0bc6b694b3103de9fed61867f1c8bd33336b913d16831431e7cb48ef1c92/mypy-1.14.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:57961db9795eb566dc1d1b4e9139ebc4c6b0cb6e7254ecde69d1552bf7613f60", size = 13013834 }, + { url = "https://files.pythonhosted.org/packages/b0/79/5f5ec47849b6df1e6943d5fd8e6632fbfc04b4fd4acfa5a5a9535d11b4e2/mypy-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:07ba89fdcc9451f2ebb02853deb6aaaa3d2239a236669a63ab3801bbf923ef5c", size = 9781231 }, + { url = "https://files.pythonhosted.org/packages/a0/b5/32dd67b69a16d088e533962e5044e51004176a9952419de0370cdaead0f8/mypy-1.14.1-py3-none-any.whl", hash = "sha256:b66a60cc4073aeb8ae00057f9c1f64d49e90f918fbcef9a977eb121da8b8f1d1", size = 2752905 }, +] + [[package]] name = "mypy" version = "1.15.0" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.13'", + "python_full_version >= '3.9' and python_full_version < '3.13'", +] dependencies = [ - { name = "mypy-extensions" }, - { name = "typing-extensions" }, + { name = "mypy-extensions", marker = "python_full_version >= '3.9'" }, + { name = "tomli", marker = "python_full_version >= '3.9' and python_full_version < '3.11.0'" }, + { name = "typing-extensions", marker = "python_full_version >= '3.9'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ce/43/d5e49a86afa64bd3839ea0d5b9c7103487007d728e1293f52525d6d5486a/mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43", size = 3239717 } wheels = [ + { url = "https://files.pythonhosted.org/packages/68/f8/65a7ce8d0e09b6329ad0c8d40330d100ea343bd4dd04c4f8ae26462d0a17/mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13", size = 10738433 }, + { url = "https://files.pythonhosted.org/packages/b4/95/9c0ecb8eacfe048583706249439ff52105b3f552ea9c4024166c03224270/mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559", size = 9861472 }, + { url = "https://files.pythonhosted.org/packages/84/09/9ec95e982e282e20c0d5407bc65031dfd0f0f8ecc66b69538296e06fcbee/mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b", size = 11611424 }, + { url = "https://files.pythonhosted.org/packages/78/13/f7d14e55865036a1e6a0a69580c240f43bc1f37407fe9235c0d4ef25ffb0/mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3", size = 12365450 }, + { url = "https://files.pythonhosted.org/packages/48/e1/301a73852d40c241e915ac6d7bcd7fedd47d519246db2d7b86b9d7e7a0cb/mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b", size = 12551765 }, + { url = "https://files.pythonhosted.org/packages/77/ba/c37bc323ae5fe7f3f15a28e06ab012cd0b7552886118943e90b15af31195/mypy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828", size = 9274701 }, { url = "https://files.pythonhosted.org/packages/03/bc/f6339726c627bd7ca1ce0fa56c9ae2d0144604a319e0e339bdadafbbb599/mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f", size = 10662338 }, { url = "https://files.pythonhosted.org/packages/e2/90/8dcf506ca1a09b0d17555cc00cd69aee402c203911410136cd716559efe7/mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5", size = 9787540 }, { url = "https://files.pythonhosted.org/packages/05/05/a10f9479681e5da09ef2f9426f650d7b550d4bafbef683b69aad1ba87457/mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e", size = 11538051 }, @@ -550,6 +824,12 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d2/8b/801aa06445d2de3895f59e476f38f3f8d610ef5d6908245f07d002676cbf/mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036", size = 12402541 }, { url = "https://files.pythonhosted.org/packages/c7/67/5a4268782eb77344cc613a4cf23540928e41f018a9a1ec4c6882baf20ab8/mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357", size = 12494348 }, { url = "https://files.pythonhosted.org/packages/83/3e/57bb447f7bbbfaabf1712d96f9df142624a386d98fb026a761532526057e/mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf", size = 9373648 }, + { url = "https://files.pythonhosted.org/packages/5a/fa/79cf41a55b682794abe71372151dbbf856e3008f6767057229e6649d294a/mypy-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078", size = 10737129 }, + { url = "https://files.pythonhosted.org/packages/d3/33/dd8feb2597d648de29e3da0a8bf4e1afbda472964d2a4a0052203a6f3594/mypy-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba", size = 9856335 }, + { url = "https://files.pythonhosted.org/packages/e4/b5/74508959c1b06b96674b364ffeb7ae5802646b32929b7701fc6b18447592/mypy-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5", size = 11611935 }, + { url = "https://files.pythonhosted.org/packages/6c/53/da61b9d9973efcd6507183fdad96606996191657fe79701b2c818714d573/mypy-1.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b", size = 12365827 }, + { url = "https://files.pythonhosted.org/packages/c1/72/965bd9ee89540c79a25778cc080c7e6ef40aa1eeac4d52cec7eae6eb5228/mypy-1.15.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2", size = 12541924 }, + { url = "https://files.pythonhosted.org/packages/46/d0/f41645c2eb263e6c77ada7d76f894c580c9ddb20d77f0c24d34273a4dab2/mypy-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980", size = 9271176 }, { url = "https://files.pythonhosted.org/packages/09/4e/a7d65c7322c510de2c409ff3828b03354a7c43f5a8ed458a7a131b41c7b9/mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e", size = 2221777 }, ] @@ -615,20 +895,116 @@ wheels = [ ] [[package]] -name = "pathspec" -version = "0.12.1" +name = "pillow" +version = "10.4.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191 }, +resolution-markers = [ + "python_full_version < '3.9'", +] +sdist = { url = "https://files.pythonhosted.org/packages/cd/74/ad3d526f3bf7b6d3f408b73fde271ec69dfac8b81341a318ce825f2b3812/pillow-10.4.0.tar.gz", hash = "sha256:166c1cd4d24309b30d61f79f4a9114b7b2313d7450912277855ff5dfd7cd4a06", size = 46555059 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0e/69/a31cccd538ca0b5272be2a38347f8839b97a14be104ea08b0db92f749c74/pillow-10.4.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:4d9667937cfa347525b319ae34375c37b9ee6b525440f3ef48542fcf66f2731e", size = 3509271 }, + { url = "https://files.pythonhosted.org/packages/9a/9e/4143b907be8ea0bce215f2ae4f7480027473f8b61fcedfda9d851082a5d2/pillow-10.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:543f3dc61c18dafb755773efc89aae60d06b6596a63914107f75459cf984164d", size = 3375658 }, + { url = "https://files.pythonhosted.org/packages/8a/25/1fc45761955f9359b1169aa75e241551e74ac01a09f487adaaf4c3472d11/pillow-10.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7928ecbf1ece13956b95d9cbcfc77137652b02763ba384d9ab508099a2eca856", size = 4332075 }, + { url = "https://files.pythonhosted.org/packages/5e/dd/425b95d0151e1d6c951f45051112394f130df3da67363b6bc75dc4c27aba/pillow-10.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4d49b85c4348ea0b31ea63bc75a9f3857869174e2bf17e7aba02945cd218e6f", size = 4444808 }, + { url = "https://files.pythonhosted.org/packages/b1/84/9a15cc5726cbbfe7f9f90bfb11f5d028586595907cd093815ca6644932e3/pillow-10.4.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:6c762a5b0997f5659a5ef2266abc1d8851ad7749ad9a6a5506eb23d314e4f46b", size = 4356290 }, + { url = "https://files.pythonhosted.org/packages/b5/5b/6651c288b08df3b8c1e2f8c1152201e0b25d240e22ddade0f1e242fc9fa0/pillow-10.4.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a985e028fc183bf12a77a8bbf36318db4238a3ded7fa9df1b9a133f1cb79f8fc", size = 4525163 }, + { url = "https://files.pythonhosted.org/packages/07/8b/34854bf11a83c248505c8cb0fcf8d3d0b459a2246c8809b967963b6b12ae/pillow-10.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:812f7342b0eee081eaec84d91423d1b4650bb9828eb53d8511bcef8ce5aecf1e", size = 4463100 }, + { url = "https://files.pythonhosted.org/packages/78/63/0632aee4e82476d9cbe5200c0cdf9ba41ee04ed77887432845264d81116d/pillow-10.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ac1452d2fbe4978c2eec89fb5a23b8387aba707ac72810d9490118817d9c0b46", size = 4592880 }, + { url = "https://files.pythonhosted.org/packages/df/56/b8663d7520671b4398b9d97e1ed9f583d4afcbefbda3c6188325e8c297bd/pillow-10.4.0-cp310-cp310-win32.whl", hash = "sha256:bcd5e41a859bf2e84fdc42f4edb7d9aba0a13d29a2abadccafad99de3feff984", size = 2235218 }, + { url = "https://files.pythonhosted.org/packages/f4/72/0203e94a91ddb4a9d5238434ae6c1ca10e610e8487036132ea9bf806ca2a/pillow-10.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:ecd85a8d3e79cd7158dec1c9e5808e821feea088e2f69a974db5edf84dc53141", size = 2554487 }, + { url = "https://files.pythonhosted.org/packages/bd/52/7e7e93d7a6e4290543f17dc6f7d3af4bd0b3dd9926e2e8a35ac2282bc5f4/pillow-10.4.0-cp310-cp310-win_arm64.whl", hash = "sha256:ff337c552345e95702c5fde3158acb0625111017d0e5f24bf3acdb9cc16b90d1", size = 2243219 }, + { url = "https://files.pythonhosted.org/packages/a7/62/c9449f9c3043c37f73e7487ec4ef0c03eb9c9afc91a92b977a67b3c0bbc5/pillow-10.4.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:0a9ec697746f268507404647e531e92889890a087e03681a3606d9b920fbee3c", size = 3509265 }, + { url = "https://files.pythonhosted.org/packages/f4/5f/491dafc7bbf5a3cc1845dc0430872e8096eb9e2b6f8161509d124594ec2d/pillow-10.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfe91cb65544a1321e631e696759491ae04a2ea11d36715eca01ce07284738be", size = 3375655 }, + { url = "https://files.pythonhosted.org/packages/73/d5/c4011a76f4207a3c151134cd22a1415741e42fa5ddecec7c0182887deb3d/pillow-10.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dc6761a6efc781e6a1544206f22c80c3af4c8cf461206d46a1e6006e4429ff3", size = 4340304 }, + { url = "https://files.pythonhosted.org/packages/ac/10/c67e20445a707f7a610699bba4fe050583b688d8cd2d202572b257f46600/pillow-10.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e84b6cc6a4a3d76c153a6b19270b3526a5a8ed6b09501d3af891daa2a9de7d6", size = 4452804 }, + { url = "https://files.pythonhosted.org/packages/a9/83/6523837906d1da2b269dee787e31df3b0acb12e3d08f024965a3e7f64665/pillow-10.4.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:bbc527b519bd3aa9d7f429d152fea69f9ad37c95f0b02aebddff592688998abe", size = 4365126 }, + { url = "https://files.pythonhosted.org/packages/ba/e5/8c68ff608a4203085158cff5cc2a3c534ec384536d9438c405ed6370d080/pillow-10.4.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:76a911dfe51a36041f2e756b00f96ed84677cdeb75d25c767f296c1c1eda1319", size = 4533541 }, + { url = "https://files.pythonhosted.org/packages/f4/7c/01b8dbdca5bc6785573f4cee96e2358b0918b7b2c7b60d8b6f3abf87a070/pillow-10.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:59291fb29317122398786c2d44427bbd1a6d7ff54017075b22be9d21aa59bd8d", size = 4471616 }, + { url = "https://files.pythonhosted.org/packages/c8/57/2899b82394a35a0fbfd352e290945440e3b3785655a03365c0ca8279f351/pillow-10.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:416d3a5d0e8cfe4f27f574362435bc9bae57f679a7158e0096ad2beb427b8696", size = 4600802 }, + { url = "https://files.pythonhosted.org/packages/4d/d7/a44f193d4c26e58ee5d2d9db3d4854b2cfb5b5e08d360a5e03fe987c0086/pillow-10.4.0-cp311-cp311-win32.whl", hash = "sha256:7086cc1d5eebb91ad24ded9f58bec6c688e9f0ed7eb3dbbf1e4800280a896496", size = 2235213 }, + { url = "https://files.pythonhosted.org/packages/c1/d0/5866318eec2b801cdb8c82abf190c8343d8a1cd8bf5a0c17444a6f268291/pillow-10.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cbed61494057c0f83b83eb3a310f0bf774b09513307c434d4366ed64f4128a91", size = 2554498 }, + { url = "https://files.pythonhosted.org/packages/d4/c8/310ac16ac2b97e902d9eb438688de0d961660a87703ad1561fd3dfbd2aa0/pillow-10.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:f5f0c3e969c8f12dd2bb7e0b15d5c468b51e5017e01e2e867335c81903046a22", size = 2243219 }, + { url = "https://files.pythonhosted.org/packages/05/cb/0353013dc30c02a8be34eb91d25e4e4cf594b59e5a55ea1128fde1e5f8ea/pillow-10.4.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:673655af3eadf4df6b5457033f086e90299fdd7a47983a13827acf7459c15d94", size = 3509350 }, + { url = "https://files.pythonhosted.org/packages/e7/cf/5c558a0f247e0bf9cec92bff9b46ae6474dd736f6d906315e60e4075f737/pillow-10.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:866b6942a92f56300012f5fbac71f2d610312ee65e22f1aa2609e491284e5597", size = 3374980 }, + { url = "https://files.pythonhosted.org/packages/84/48/6e394b86369a4eb68b8a1382c78dc092245af517385c086c5094e3b34428/pillow-10.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29dbdc4207642ea6aad70fbde1a9338753d33fb23ed6956e706936706f52dd80", size = 4343799 }, + { url = "https://files.pythonhosted.org/packages/3b/f3/a8c6c11fa84b59b9df0cd5694492da8c039a24cd159f0f6918690105c3be/pillow-10.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf2342ac639c4cf38799a44950bbc2dfcb685f052b9e262f446482afaf4bffca", size = 4459973 }, + { url = "https://files.pythonhosted.org/packages/7d/1b/c14b4197b80150fb64453585247e6fb2e1d93761fa0fa9cf63b102fde822/pillow-10.4.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:f5b92f4d70791b4a67157321c4e8225d60b119c5cc9aee8ecf153aace4aad4ef", size = 4370054 }, + { url = "https://files.pythonhosted.org/packages/55/77/40daddf677897a923d5d33329acd52a2144d54a9644f2a5422c028c6bf2d/pillow-10.4.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:86dcb5a1eb778d8b25659d5e4341269e8590ad6b4e8b44d9f4b07f8d136c414a", size = 4539484 }, + { url = "https://files.pythonhosted.org/packages/40/54/90de3e4256b1207300fb2b1d7168dd912a2fb4b2401e439ba23c2b2cabde/pillow-10.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:780c072c2e11c9b2c7ca37f9a2ee8ba66f44367ac3e5c7832afcfe5104fd6d1b", size = 4477375 }, + { url = "https://files.pythonhosted.org/packages/13/24/1bfba52f44193860918ff7c93d03d95e3f8748ca1de3ceaf11157a14cf16/pillow-10.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:37fb69d905be665f68f28a8bba3c6d3223c8efe1edf14cc4cfa06c241f8c81d9", size = 4608773 }, + { url = "https://files.pythonhosted.org/packages/55/04/5e6de6e6120451ec0c24516c41dbaf80cce1b6451f96561235ef2429da2e/pillow-10.4.0-cp312-cp312-win32.whl", hash = "sha256:7dfecdbad5c301d7b5bde160150b4db4c659cee2b69589705b6f8a0c509d9f42", size = 2235690 }, + { url = "https://files.pythonhosted.org/packages/74/0a/d4ce3c44bca8635bd29a2eab5aa181b654a734a29b263ca8efe013beea98/pillow-10.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:1d846aea995ad352d4bdcc847535bd56e0fd88d36829d2c90be880ef1ee4668a", size = 2554951 }, + { url = "https://files.pythonhosted.org/packages/b5/ca/184349ee40f2e92439be9b3502ae6cfc43ac4b50bc4fc6b3de7957563894/pillow-10.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:e553cad5179a66ba15bb18b353a19020e73a7921296a7979c4a2b7f6a5cd57f9", size = 2243427 }, + { url = "https://files.pythonhosted.org/packages/c3/00/706cebe7c2c12a6318aabe5d354836f54adff7156fd9e1bd6c89f4ba0e98/pillow-10.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8bc1a764ed8c957a2e9cacf97c8b2b053b70307cf2996aafd70e91a082e70df3", size = 3525685 }, + { url = "https://files.pythonhosted.org/packages/cf/76/f658cbfa49405e5ecbfb9ba42d07074ad9792031267e782d409fd8fe7c69/pillow-10.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6209bb41dc692ddfee4942517c19ee81b86c864b626dbfca272ec0f7cff5d9fb", size = 3374883 }, + { url = "https://files.pythonhosted.org/packages/46/2b/99c28c4379a85e65378211971c0b430d9c7234b1ec4d59b2668f6299e011/pillow-10.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bee197b30783295d2eb680b311af15a20a8b24024a19c3a26431ff83eb8d1f70", size = 4339837 }, + { url = "https://files.pythonhosted.org/packages/f1/74/b1ec314f624c0c43711fdf0d8076f82d9d802afd58f1d62c2a86878e8615/pillow-10.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ef61f5dd14c300786318482456481463b9d6b91ebe5ef12f405afbba77ed0be", size = 4455562 }, + { url = "https://files.pythonhosted.org/packages/4a/2a/4b04157cb7b9c74372fa867096a1607e6fedad93a44deeff553ccd307868/pillow-10.4.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:297e388da6e248c98bc4a02e018966af0c5f92dfacf5a5ca22fa01cb3179bca0", size = 4366761 }, + { url = "https://files.pythonhosted.org/packages/ac/7b/8f1d815c1a6a268fe90481232c98dd0e5fa8c75e341a75f060037bd5ceae/pillow-10.4.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:e4db64794ccdf6cb83a59d73405f63adbe2a1887012e308828596100a0b2f6cc", size = 4536767 }, + { url = "https://files.pythonhosted.org/packages/e5/77/05fa64d1f45d12c22c314e7b97398ffb28ef2813a485465017b7978b3ce7/pillow-10.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bd2880a07482090a3bcb01f4265f1936a903d70bc740bfcb1fd4e8a2ffe5cf5a", size = 4477989 }, + { url = "https://files.pythonhosted.org/packages/12/63/b0397cfc2caae05c3fb2f4ed1b4fc4fc878f0243510a7a6034ca59726494/pillow-10.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b35b21b819ac1dbd1233317adeecd63495f6babf21b7b2512d244ff6c6ce309", size = 4610255 }, + { url = "https://files.pythonhosted.org/packages/7b/f9/cfaa5082ca9bc4a6de66ffe1c12c2d90bf09c309a5f52b27759a596900e7/pillow-10.4.0-cp313-cp313-win32.whl", hash = "sha256:551d3fd6e9dc15e4c1eb6fc4ba2b39c0c7933fa113b220057a34f4bb3268a060", size = 2235603 }, + { url = "https://files.pythonhosted.org/packages/01/6a/30ff0eef6e0c0e71e55ded56a38d4859bf9d3634a94a88743897b5f96936/pillow-10.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:030abdbe43ee02e0de642aee345efa443740aa4d828bfe8e2eb11922ea6a21ea", size = 2554972 }, + { url = "https://files.pythonhosted.org/packages/48/2c/2e0a52890f269435eee38b21c8218e102c621fe8d8df8b9dd06fabf879ba/pillow-10.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:5b001114dd152cfd6b23befeb28d7aee43553e2402c9f159807bf55f33af8a8d", size = 2243375 }, + { url = "https://files.pythonhosted.org/packages/56/70/f40009702a477ce87d8d9faaa4de51d6562b3445d7a314accd06e4ffb01d/pillow-10.4.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:8d4d5063501b6dd4024b8ac2f04962d661222d120381272deea52e3fc52d3736", size = 3509213 }, + { url = "https://files.pythonhosted.org/packages/10/43/105823d233c5e5d31cea13428f4474ded9d961652307800979a59d6a4276/pillow-10.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7c1ee6f42250df403c5f103cbd2768a28fe1a0ea1f0f03fe151c8741e1469c8b", size = 3375883 }, + { url = "https://files.pythonhosted.org/packages/3c/ad/7850c10bac468a20c918f6a5dbba9ecd106ea1cdc5db3c35e33a60570408/pillow-10.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b15e02e9bb4c21e39876698abf233c8c579127986f8207200bc8a8f6bb27acf2", size = 4330810 }, + { url = "https://files.pythonhosted.org/packages/84/4c/69bbed9e436ac22f9ed193a2b64f64d68fcfbc9f4106249dc7ed4889907b/pillow-10.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a8d4bade9952ea9a77d0c3e49cbd8b2890a399422258a77f357b9cc9be8d680", size = 4444341 }, + { url = "https://files.pythonhosted.org/packages/8f/4f/c183c63828a3f37bf09644ce94cbf72d4929b033b109160a5379c2885932/pillow-10.4.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:43efea75eb06b95d1631cb784aa40156177bf9dd5b4b03ff38979e048258bc6b", size = 4356005 }, + { url = "https://files.pythonhosted.org/packages/fb/ad/435fe29865f98a8fbdc64add8875a6e4f8c97749a93577a8919ec6f32c64/pillow-10.4.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:950be4d8ba92aca4b2bb0741285a46bfae3ca699ef913ec8416c1b78eadd64cd", size = 4525201 }, + { url = "https://files.pythonhosted.org/packages/80/74/be8bf8acdfd70e91f905a12ae13cfb2e17c0f1da745c40141e26d0971ff5/pillow-10.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d7480af14364494365e89d6fddc510a13e5a2c3584cb19ef65415ca57252fb84", size = 4460635 }, + { url = "https://files.pythonhosted.org/packages/e4/90/763616e66dc9ad59c9b7fb58f863755e7934ef122e52349f62c7742b82d3/pillow-10.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:73664fe514b34c8f02452ffb73b7a92c6774e39a647087f83d67f010eb9a0cf0", size = 4590283 }, + { url = "https://files.pythonhosted.org/packages/69/66/03002cb5b2c27bb519cba63b9f9aa3709c6f7a5d3b285406c01f03fb77e5/pillow-10.4.0-cp38-cp38-win32.whl", hash = "sha256:e88d5e6ad0d026fba7bdab8c3f225a69f063f116462c49892b0149e21b6c0a0e", size = 2235185 }, + { url = "https://files.pythonhosted.org/packages/f2/75/3cb820b2812405fc7feb3d0deb701ef0c3de93dc02597115e00704591bc9/pillow-10.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:5161eef006d335e46895297f642341111945e2c1c899eb406882a6c61a4357ab", size = 2554594 }, + { url = "https://files.pythonhosted.org/packages/31/85/955fa5400fa8039921f630372cfe5056eed6e1b8e0430ee4507d7de48832/pillow-10.4.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:0ae24a547e8b711ccaaf99c9ae3cd975470e1a30caa80a6aaee9a2f19c05701d", size = 3509283 }, + { url = "https://files.pythonhosted.org/packages/23/9c/343827267eb28d41cd82b4180d33b10d868af9077abcec0af9793aa77d2d/pillow-10.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:298478fe4f77a4408895605f3482b6cc6222c018b2ce565c2b6b9c354ac3229b", size = 3375691 }, + { url = "https://files.pythonhosted.org/packages/60/a3/7ebbeabcd341eab722896d1a5b59a3df98c4b4d26cf4b0385f8aa94296f7/pillow-10.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:134ace6dc392116566980ee7436477d844520a26a4b1bd4053f6f47d096997fd", size = 4328295 }, + { url = "https://files.pythonhosted.org/packages/32/3f/c02268d0c6fb6b3958bdda673c17b315c821d97df29ae6969f20fb49388a/pillow-10.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:930044bb7679ab003b14023138b50181899da3f25de50e9dbee23b61b4de2126", size = 4440810 }, + { url = "https://files.pythonhosted.org/packages/67/5d/1c93c8cc35f2fdd3d6cc7e4ad72d203902859a2867de6ad957d9b708eb8d/pillow-10.4.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:c76e5786951e72ed3686e122d14c5d7012f16c8303a674d18cdcd6d89557fc5b", size = 4352283 }, + { url = "https://files.pythonhosted.org/packages/bc/a8/8655557c9c7202b8abbd001f61ff36711cefaf750debcaa1c24d154ef602/pillow-10.4.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:b2724fdb354a868ddf9a880cb84d102da914e99119211ef7ecbdc613b8c96b3c", size = 4521800 }, + { url = "https://files.pythonhosted.org/packages/58/78/6f95797af64d137124f68af1bdaa13b5332da282b86031f6fa70cf368261/pillow-10.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dbc6ae66518ab3c5847659e9988c3b60dc94ffb48ef9168656e0019a93dbf8a1", size = 4459177 }, + { url = "https://files.pythonhosted.org/packages/8a/6d/2b3ce34f1c4266d79a78c9a51d1289a33c3c02833fe294ef0dcbb9cba4ed/pillow-10.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:06b2f7898047ae93fad74467ec3d28fe84f7831370e3c258afa533f81ef7f3df", size = 4589079 }, + { url = "https://files.pythonhosted.org/packages/e3/e0/456258c74da1ff5bf8ef1eab06a95ca994d8b9ed44c01d45c3f8cbd1db7e/pillow-10.4.0-cp39-cp39-win32.whl", hash = "sha256:7970285ab628a3779aecc35823296a7869f889b8329c16ad5a71e4901a3dc4ef", size = 2235247 }, + { url = "https://files.pythonhosted.org/packages/37/f8/bef952bdb32aa53741f58bf21798642209e994edc3f6598f337f23d5400a/pillow-10.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:961a7293b2457b405967af9c77dcaa43cc1a8cd50d23c532e62d48ab6cdd56f5", size = 2554479 }, + { url = "https://files.pythonhosted.org/packages/bb/8e/805201619cad6651eef5fc1fdef913804baf00053461522fabbc5588ea12/pillow-10.4.0-cp39-cp39-win_arm64.whl", hash = "sha256:32cda9e3d601a52baccb2856b8ea1fc213c90b340c542dcef77140dfa3278a9e", size = 2243226 }, + { url = "https://files.pythonhosted.org/packages/38/30/095d4f55f3a053392f75e2eae45eba3228452783bab3d9a920b951ac495c/pillow-10.4.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:5b4815f2e65b30f5fbae9dfffa8636d992d49705723fe86a3661806e069352d4", size = 3493889 }, + { url = "https://files.pythonhosted.org/packages/f3/e8/4ff79788803a5fcd5dc35efdc9386af153569853767bff74540725b45863/pillow-10.4.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:8f0aef4ef59694b12cadee839e2ba6afeab89c0f39a3adc02ed51d109117b8da", size = 3346160 }, + { url = "https://files.pythonhosted.org/packages/d7/ac/4184edd511b14f760c73f5bb8a5d6fd85c591c8aff7c2229677a355c4179/pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f4727572e2918acaa9077c919cbbeb73bd2b3ebcfe033b72f858fc9fbef0026", size = 3435020 }, + { url = "https://files.pythonhosted.org/packages/da/21/1749cd09160149c0a246a81d646e05f35041619ce76f6493d6a96e8d1103/pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff25afb18123cea58a591ea0244b92eb1e61a1fd497bf6d6384f09bc3262ec3e", size = 3490539 }, + { url = "https://files.pythonhosted.org/packages/b6/f5/f71fe1888b96083b3f6dfa0709101f61fc9e972c0c8d04e9d93ccef2a045/pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:dc3e2db6ba09ffd7d02ae9141cfa0ae23393ee7687248d46a7507b75d610f4f5", size = 3476125 }, + { url = "https://files.pythonhosted.org/packages/96/b9/c0362c54290a31866c3526848583a2f45a535aa9d725fd31e25d318c805f/pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:02a2be69f9c9b8c1e97cf2713e789d4e398c751ecfd9967c18d0ce304efbf885", size = 3579373 }, + { url = "https://files.pythonhosted.org/packages/52/3b/ce7a01026a7cf46e5452afa86f97a5e88ca97f562cafa76570178ab56d8d/pillow-10.4.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:0755ffd4a0c6f267cccbae2e9903d95477ca2f77c4fcf3a3a09570001856c8a5", size = 2554661 }, + { url = "https://files.pythonhosted.org/packages/e1/1f/5a9fcd6ced51633c22481417e11b1b47d723f64fb536dfd67c015eb7f0ab/pillow-10.4.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:a02364621fe369e06200d4a16558e056fe2805d3468350df3aef21e00d26214b", size = 3493850 }, + { url = "https://files.pythonhosted.org/packages/cb/e6/3ea4755ed5320cb62aa6be2f6de47b058c6550f752dd050e86f694c59798/pillow-10.4.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:1b5dea9831a90e9d0721ec417a80d4cbd7022093ac38a568db2dd78363b00908", size = 3346118 }, + { url = "https://files.pythonhosted.org/packages/0a/22/492f9f61e4648422b6ca39268ec8139277a5b34648d28f400faac14e0f48/pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b885f89040bb8c4a1573566bbb2f44f5c505ef6e74cec7ab9068c900047f04b", size = 3434958 }, + { url = "https://files.pythonhosted.org/packages/f9/19/559a48ad4045704bb0547965b9a9345f5cd461347d977a56d178db28819e/pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87dd88ded2e6d74d31e1e0a99a726a6765cda32d00ba72dc37f0651f306daaa8", size = 3490340 }, + { url = "https://files.pythonhosted.org/packages/d9/de/cebaca6fb79905b3a1aa0281d238769df3fb2ede34fd7c0caa286575915a/pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:2db98790afc70118bd0255c2eeb465e9767ecf1f3c25f9a1abb8ffc8cfd1fe0a", size = 3476048 }, + { url = "https://files.pythonhosted.org/packages/71/f0/86d5b2f04693b0116a01d75302b0a307800a90d6c351a8aa4f8ae76cd499/pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f7baece4ce06bade126fb84b8af1c33439a76d8a6fd818970215e0560ca28c27", size = 3579366 }, + { url = "https://files.pythonhosted.org/packages/37/ae/2dbfc38cc4fd14aceea14bc440d5151b21f64c4c3ba3f6f4191610b7ee5d/pillow-10.4.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:cfdd747216947628af7b259d274771d84db2268ca062dd5faf373639d00113a3", size = 2554652 }, ] [[package]] name = "pillow" version = "11.1.0" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.13'", + "python_full_version >= '3.9' and python_full_version < '3.13'", +] sdist = { url = "https://files.pythonhosted.org/packages/f3/af/c097e544e7bd278333db77933e535098c259609c4eb3b85381109602fb5b/pillow-11.1.0.tar.gz", hash = "sha256:368da70808b36d73b4b390a8ffac11069f8a5c85f29eff1f1b01bcf3ef5b2a20", size = 46742715 } wheels = [ + { url = "https://files.pythonhosted.org/packages/50/1c/2dcea34ac3d7bc96a1fd1bd0a6e06a57c67167fec2cff8d95d88229a8817/pillow-11.1.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:e1abe69aca89514737465752b4bcaf8016de61b3be1397a8fc260ba33321b3a8", size = 3229983 }, + { url = "https://files.pythonhosted.org/packages/14/ca/6bec3df25e4c88432681de94a3531cc738bd85dea6c7aa6ab6f81ad8bd11/pillow-11.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c640e5a06869c75994624551f45e5506e4256562ead981cce820d5ab39ae2192", size = 3101831 }, + { url = "https://files.pythonhosted.org/packages/d4/2c/668e18e5521e46eb9667b09e501d8e07049eb5bfe39d56be0724a43117e6/pillow-11.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a07dba04c5e22824816b2615ad7a7484432d7f540e6fa86af60d2de57b0fcee2", size = 4314074 }, + { url = "https://files.pythonhosted.org/packages/02/80/79f99b714f0fc25f6a8499ecfd1f810df12aec170ea1e32a4f75746051ce/pillow-11.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e267b0ed063341f3e60acd25c05200df4193e15a4a5807075cd71225a2386e26", size = 4394933 }, + { url = "https://files.pythonhosted.org/packages/81/aa/8d4ad25dc11fd10a2001d5b8a80fdc0e564ac33b293bdfe04ed387e0fd95/pillow-11.1.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:bd165131fd51697e22421d0e467997ad31621b74bfc0b75956608cb2906dda07", size = 4353349 }, + { url = "https://files.pythonhosted.org/packages/84/7a/cd0c3eaf4a28cb2a74bdd19129f7726277a7f30c4f8424cd27a62987d864/pillow-11.1.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:abc56501c3fd148d60659aae0af6ddc149660469082859fa7b066a298bde9482", size = 4476532 }, + { url = "https://files.pythonhosted.org/packages/8f/8b/a907fdd3ae8f01c7670dfb1499c53c28e217c338b47a813af8d815e7ce97/pillow-11.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:54ce1c9a16a9561b6d6d8cb30089ab1e5eb66918cb47d457bd996ef34182922e", size = 4279789 }, + { url = "https://files.pythonhosted.org/packages/6f/9a/9f139d9e8cccd661c3efbf6898967a9a337eb2e9be2b454ba0a09533100d/pillow-11.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:73ddde795ee9b06257dac5ad42fcb07f3b9b813f8c1f7f870f402f4dc54b5269", size = 4413131 }, + { url = "https://files.pythonhosted.org/packages/a8/68/0d8d461f42a3f37432203c8e6df94da10ac8081b6d35af1c203bf3111088/pillow-11.1.0-cp310-cp310-win32.whl", hash = "sha256:3a5fe20a7b66e8135d7fd617b13272626a28278d0e578c98720d9ba4b2439d49", size = 2291213 }, + { url = "https://files.pythonhosted.org/packages/14/81/d0dff759a74ba87715509af9f6cb21fa21d93b02b3316ed43bda83664db9/pillow-11.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:b6123aa4a59d75f06e9dd3dac5bf8bc9aa383121bb3dd9a7a612e05eabc9961a", size = 2625725 }, + { url = "https://files.pythonhosted.org/packages/ce/1f/8d50c096a1d58ef0584ddc37e6f602828515219e9d2428e14ce50f5ecad1/pillow-11.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:a76da0a31da6fcae4210aa94fd779c65c75786bc9af06289cd1c184451ef7a65", size = 2375213 }, { url = "https://files.pythonhosted.org/packages/dd/d6/2000bfd8d5414fb70cbbe52c8332f2283ff30ed66a9cde42716c8ecbe22c/pillow-11.1.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:e06695e0326d05b06833b40b7ef477e475d0b1ba3a6d27da1bb48c23209bf457", size = 3229968 }, { url = "https://files.pythonhosted.org/packages/d9/45/3fe487010dd9ce0a06adf9b8ff4f273cc0a44536e234b0fad3532a42c15b/pillow-11.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96f82000e12f23e4f29346e42702b6ed9a2f2fea34a740dd5ffffcc8c539eb35", size = 3101806 }, { url = "https://files.pythonhosted.org/packages/e3/72/776b3629c47d9d5f1c160113158a7a7ad177688d3a1159cd3b62ded5a33a/pillow-11.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3cd561ded2cf2bbae44d4605837221b987c216cff94f49dfeed63488bb228d2", size = 4322283 }, @@ -670,6 +1046,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e5/fb/a7960e838bc5df57a2ce23183bfd2290d97c33028b96bde332a9057834d3/pillow-11.1.0-cp313-cp313t-win32.whl", hash = "sha256:dda60aa465b861324e65a78c9f5cf0f4bc713e4309f83bc387be158b077963d9", size = 2295494 }, { url = "https://files.pythonhosted.org/packages/d7/6c/6ec83ee2f6f0fda8d4cf89045c6be4b0373ebfc363ba8538f8c999f63fcd/pillow-11.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ad5db5781c774ab9a9b2c4302bbf0c1014960a0a7be63278d13ae6fdf88126fe", size = 2631595 }, { url = "https://files.pythonhosted.org/packages/cf/6c/41c21c6c8af92b9fea313aa47c75de49e2f9a467964ee33eb0135d47eb64/pillow-11.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:67cd427c68926108778a9005f2a04adbd5e67c442ed21d95389fe1d595458756", size = 2377651 }, + { url = "https://files.pythonhosted.org/packages/9a/1f/9df5ac77491fddd2e36c352d16976dc11fbe6ab842f5df85fd7e31b847b9/pillow-11.1.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:bf902d7413c82a1bfa08b06a070876132a5ae6b2388e2712aab3a7cbc02205c6", size = 3229995 }, + { url = "https://files.pythonhosted.org/packages/a6/62/c7b359e924dca274173b04922ac06aa63614f7e934d132f2fe1d852509aa/pillow-11.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c1eec9d950b6fe688edee07138993e54ee4ae634c51443cfb7c1e7613322718e", size = 3101890 }, + { url = "https://files.pythonhosted.org/packages/7b/63/136f21340a434de895b62bcf2c386005a8aa24066c4facd619f5e0e9f283/pillow-11.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e275ee4cb11c262bd108ab2081f750db2a1c0b8c12c1897f27b160c8bd57bbc", size = 4310366 }, + { url = "https://files.pythonhosted.org/packages/f6/46/0bd0ca03d9d1164a7fa33d285ef6d1c438e963d0c8770e4c5b3737ef5abe/pillow-11.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4db853948ce4e718f2fc775b75c37ba2efb6aaea41a1a5fc57f0af59eee774b2", size = 4391582 }, + { url = "https://files.pythonhosted.org/packages/0c/55/f182db572b28bd833b8e806f933f782ceb2df64c40e4d8bd3d4226a46eca/pillow-11.1.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:ab8a209b8485d3db694fa97a896d96dd6533d63c22829043fd9de627060beade", size = 4350278 }, + { url = "https://files.pythonhosted.org/packages/75/fb/e330fdbbcbc4744214b5f53b84d9d8a9f4ffbebc2e9c2ac10475386e3296/pillow-11.1.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:54251ef02a2309b5eec99d151ebf5c9904b77976c8abdcbce7891ed22df53884", size = 4471768 }, + { url = "https://files.pythonhosted.org/packages/eb/51/20ee6c4da4448d7a67ffb720a5fcdb965115a78e211a1f58f9845ae15f86/pillow-11.1.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5bb94705aea800051a743aa4874bb1397d4695fb0583ba5e425ee0328757f196", size = 4276549 }, + { url = "https://files.pythonhosted.org/packages/37/f2/a25c0bdaa6d6fd5cc3d4a6f65b5a7ea46e7af58bee00a98efe0a5af79c58/pillow-11.1.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:89dbdb3e6e9594d512780a5a1c42801879628b38e3efc7038094430844e271d8", size = 4409350 }, + { url = "https://files.pythonhosted.org/packages/12/a7/06687947604cd3e47abeea1b78b65d34ffce7feab03cfe0dd985f115dca3/pillow-11.1.0-cp39-cp39-win32.whl", hash = "sha256:e5449ca63da169a2e6068dd0e2fcc8d91f9558aba89ff6d02121ca8ab11e79e5", size = 2291271 }, + { url = "https://files.pythonhosted.org/packages/21/a6/f51d47675940b5c63b08ff0575b3518428b4acb891f88526fa4ee1edab6f/pillow-11.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:3362c6ca227e65c54bf71a5f88b3d4565ff1bcbc63ae72c34b07bbb1cc59a43f", size = 2625783 }, + { url = "https://files.pythonhosted.org/packages/95/56/97750bd33e68648fa432dfadcb8ede7624bd905822d42262d34bcebdd9d7/pillow-11.1.0-cp39-cp39-win_arm64.whl", hash = "sha256:b20be51b37a75cc54c2c55def3fa2c65bb94ba859dde241cd0a4fd302de5ae0a", size = 2375193 }, + { url = "https://files.pythonhosted.org/packages/fa/c5/389961578fb677b8b3244fcd934f720ed25a148b9a5cc81c91bdf59d8588/pillow-11.1.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:8c730dc3a83e5ac137fbc92dfcfe1511ce3b2b5d7578315b63dbbb76f7f51d90", size = 3198345 }, + { url = "https://files.pythonhosted.org/packages/c4/fa/803c0e50ffee74d4b965229e816af55276eac1d5806712de86f9371858fd/pillow-11.1.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:7d33d2fae0e8b170b6a6c57400e077412240f6f5bb2a342cf1ee512a787942bb", size = 3072938 }, + { url = "https://files.pythonhosted.org/packages/dc/67/2a3a5f8012b5d8c63fe53958ba906c1b1d0482ebed5618057ef4d22f8076/pillow-11.1.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a8d65b38173085f24bc07f8b6c505cbb7418009fa1a1fcb111b1f4961814a442", size = 3400049 }, + { url = "https://files.pythonhosted.org/packages/e5/a0/514f0d317446c98c478d1872497eb92e7cde67003fed74f696441e647446/pillow-11.1.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:015c6e863faa4779251436db398ae75051469f7c903b043a48f078e437656f83", size = 3422431 }, + { url = "https://files.pythonhosted.org/packages/cd/00/20f40a935514037b7d3f87adfc87d2c538430ea625b63b3af8c3f5578e72/pillow-11.1.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d44ff19eea13ae4acdaaab0179fa68c0c6f2f45d66a4d8ec1eda7d6cecbcc15f", size = 3446208 }, + { url = "https://files.pythonhosted.org/packages/28/3c/7de681727963043e093c72e6c3348411b0185eab3263100d4490234ba2f6/pillow-11.1.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:d3d8da4a631471dfaf94c10c85f5277b1f8e42ac42bade1ac67da4b4a7359b73", size = 3509746 }, + { url = "https://files.pythonhosted.org/packages/41/67/936f9814bdd74b2dfd4822f1f7725ab5d8ff4103919a1664eb4874c58b2f/pillow-11.1.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:4637b88343166249fe8aa94e7c4a62a180c4b3898283bb5d3d2fd5fe10d8e4e0", size = 2626353 }, ] [[package]] @@ -708,11 +1102,15 @@ version = "2.9.10" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/62/51/2007ea29e605957a17ac6357115d0c1a1b60c8c984951c19419b3474cdfd/psycopg2-2.9.10.tar.gz", hash = "sha256:12ec0b40b0273f95296233e8750441339298e6a572f7039da5b260e3c8b60e11", size = 385672 } wheels = [ + { url = "https://files.pythonhosted.org/packages/0a/a9/146b6bdc0d33539a359f5e134ee6dda9173fb8121c5b96af33fa299e50c4/psycopg2-2.9.10-cp310-cp310-win32.whl", hash = "sha256:5df2b672140f95adb453af93a7d669d7a7bf0a56bcd26f1502329166f4a61716", size = 1024527 }, + { url = "https://files.pythonhosted.org/packages/47/50/c509e56f725fd2572b59b69bd964edaf064deebf1c896b2452f6b46fdfb3/psycopg2-2.9.10-cp310-cp310-win_amd64.whl", hash = "sha256:c6f7b8561225f9e711a9c47087388a97fdc948211c10a4bccbf0ba68ab7b3b5a", size = 1163735 }, { url = "https://files.pythonhosted.org/packages/20/a2/c51ca3e667c34e7852157b665e3d49418e68182081060231d514dd823225/psycopg2-2.9.10-cp311-cp311-win32.whl", hash = "sha256:47c4f9875125344f4c2b870e41b6aad585901318068acd01de93f3677a6522c2", size = 1024538 }, { url = "https://files.pythonhosted.org/packages/33/39/5a9a229bb5414abeb86e33b8fc8143ab0aecce5a7f698a53e31367d30caa/psycopg2-2.9.10-cp311-cp311-win_amd64.whl", hash = "sha256:0435034157049f6846e95103bd8f5a668788dd913a7c30162ca9503fdf542cb4", size = 1163736 }, { url = "https://files.pythonhosted.org/packages/3d/16/4623fad6076448df21c1a870c93a9774ad8a7b4dd1660223b59082dd8fec/psycopg2-2.9.10-cp312-cp312-win32.whl", hash = "sha256:65a63d7ab0e067e2cdb3cf266de39663203d38d6a8ed97f5ca0cb315c73fe067", size = 1025113 }, { url = "https://files.pythonhosted.org/packages/66/de/baed128ae0fc07460d9399d82e631ea31a1f171c0c4ae18f9808ac6759e3/psycopg2-2.9.10-cp312-cp312-win_amd64.whl", hash = "sha256:4a579d6243da40a7b3182e0430493dbd55950c493d8c68f4eec0b302f6bbf20e", size = 1163951 }, { url = "https://files.pythonhosted.org/packages/ae/49/a6cfc94a9c483b1fa401fbcb23aca7892f60c7269c5ffa2ac408364f80dc/psycopg2-2.9.10-cp313-cp313-win_amd64.whl", hash = "sha256:91fd603a2155da8d0cfcdbf8ab24a2d54bca72795b90d2a3ed2b6da8d979dee2", size = 2569060 }, + { url = "https://files.pythonhosted.org/packages/5f/29/bc9639b9c50abd93a8274fd2deffbf70b2a65aa9e7881e63ea6bc4319e84/psycopg2-2.9.10-cp39-cp39-win32.whl", hash = "sha256:9d5b3b94b79a844a986d029eee38998232451119ad653aea42bb9220a8c5066b", size = 1025259 }, + { url = "https://files.pythonhosted.org/packages/2c/f8/0be7d99d24656b689d83ac167240c3527efb0b161d814fb1dd58329ddf75/psycopg2-2.9.10-cp39-cp39-win_amd64.whl", hash = "sha256:88138c8dedcbfa96408023ea2b0c369eda40fe5d75002c0964c78f46f11fa442", size = 1163878 }, ] [[package]] @@ -733,12 +1131,33 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293 }, ] +[[package]] +name = "pyproject-api" +version = "1.8.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.9'", +] +dependencies = [ + { name = "packaging", marker = "python_full_version < '3.9'" }, + { name = "tomli", marker = "python_full_version < '3.9'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bb/19/441e0624a8afedd15bbcce96df1b80479dd0ff0d965f5ce8fde4f2f6ffad/pyproject_api-1.8.0.tar.gz", hash = "sha256:77b8049f2feb5d33eefcc21b57f1e279636277a8ac8ad6b5871037b243778496", size = 22340 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ba/f4/3c4ddfcc0c19c217c6de513842d286de8021af2f2ab79bbb86c00342d778/pyproject_api-1.8.0-py3-none-any.whl", hash = "sha256:3d7d347a047afe796fd5d1885b1e391ba29be7169bd2f102fcd378f04273d228", size = 13100 }, +] + [[package]] name = "pyproject-api" version = "1.9.0" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.13'", + "python_full_version >= '3.9' and python_full_version < '3.13'", +] dependencies = [ - { name = "packaging" }, + { name = "packaging", marker = "python_full_version >= '3.9'" }, + { name = "tomli", marker = "python_full_version >= '3.9' and python_full_version < '3.11.0'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/7e/66/fdc17e94486836eda4ba7113c0db9ac7e2f4eea1b968ee09de2fe75e391b/pyproject_api-1.9.0.tar.gz", hash = "sha256:7e8a9854b2dfb49454fae421cb86af43efbb2b2454e5646ffb7623540321ae6e", size = 22714 } wheels = [ @@ -769,9 +1188,11 @@ version = "8.3.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11.0'" }, { name = "iniconfig" }, { name = "packaging" }, { name = "pluggy" }, + { name = "tomli", marker = "python_full_version < '3.11.0'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/05/35/30e0d83068951d90a01852cb1cef56e5d8a09d20c7f511634cc2f7e0372a/pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761", size = 1445919 } wheels = [ @@ -788,13 +1209,33 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/d1/15/082fd0428aab33d2bafa014f3beb241830427ba803a8912a5aaeaf3a5663/pytest-cache-1.0.tar.gz", hash = "sha256:be7468edd4d3d83f1e844959fd6e3fd28e77a481440a7118d430130ea31b07a9", size = 16242 } +[[package]] +name = "pytest-cov" +version = "5.0.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.9'", +] +dependencies = [ + { name = "coverage", version = "7.6.1", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version < '3.9'" }, + { name = "pytest", marker = "python_full_version < '3.9'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/74/67/00efc8d11b630c56f15f4ad9c7f9223f1e5ec275aaae3fa9118c6a223ad2/pytest-cov-5.0.0.tar.gz", hash = "sha256:5837b58e9f6ebd335b0f8060eecce69b662415b16dc503883a02f45dfeb14857", size = 63042 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/3a/af5b4fa5961d9a1e6237b530eb87dd04aea6eb83da09d2a4073d81b54ccf/pytest_cov-5.0.0-py3-none-any.whl", hash = "sha256:4f0764a1219df53214206bf1feea4633c3b558a2925c8b59f144f682861ce652", size = 21990 }, +] + [[package]] name = "pytest-cov" version = "6.0.0" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.13'", + "python_full_version >= '3.9' and python_full_version < '3.13'", +] dependencies = [ - { name = "coverage", extra = ["toml"] }, - { name = "pytest" }, + { name = "coverage", version = "7.6.10", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version >= '3.9'" }, + { name = "pytest", marker = "python_full_version >= '3.9'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/be/45/9b538de8cef30e17c7b45ef42f538a94889ed6a16f2387a6c89e73220651/pytest-cov-6.0.0.tar.gz", hash = "sha256:fde0b595ca248bb8e2d76f020b465f3b107c9632e6a1d1705f17834c89dcadc0", size = 66945 } wheels = [ @@ -813,12 +1254,31 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/47/fe/54f387ee1b41c9ad59e48fb8368a361fad0600fe404315e31a12bacaea7d/pytest_django-4.9.0-py3-none-any.whl", hash = "sha256:1d83692cb39188682dbb419ff0393867e9904094a549a7d38a3154d5731b2b99", size = 23723 }, ] +[[package]] +name = "pytest-echo" +version = "1.7.3" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.9'", +] +dependencies = [ + { name = "pytest", marker = "python_full_version < '3.9'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/37/0e/a5dcb4a634dcbdba8a97d1201c8c8a95405e6f504e055e1e9a10e4b939d3/pytest-echo-1.7.3.tar.gz", hash = "sha256:2307af560ebbdc77967579e577f24015467fbcf80cabb9b04d225348bb8d9474", size = 13948 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/af/d2/155f0ffc8d5c1091c9b5aaec93325c4729b2474e00729f1ac320310268cc/pytest_echo-1.7.3-py2.py3-none-any.whl", hash = "sha256:683f4d2fef8dd701aeaf47db834ccc114d43f580abcfea53f3ce2ffe8166c3c0", size = 5744 }, +] + [[package]] name = "pytest-echo" version = "1.8.1" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.13'", + "python_full_version >= '3.9' and python_full_version < '3.13'", +] dependencies = [ - { name = "pytest" }, + { name = "pytest", marker = "python_full_version >= '3.9'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/4d/48/fc27028f166c25623ac0c1d401bce3a77662050edadb06d87bec1da2c63f/pytest_echo-1.8.1.tar.gz", hash = "sha256:7d765b4ddac93468fa1d303e70c48ad9e38479b4d122d5ae019919bb7fed0c2a", size = 14863 } wheels = [ @@ -851,21 +1311,43 @@ name = "readme" version = "0.7.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "readme-renderer" }, + { name = "readme-renderer", version = "43.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "readme-renderer", version = "44.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/e2/b5/831f3f29e64107a4222d7156a45f81bfdc6f0f29af9af96f3fe173a5d060/readme-0.7.1.tar.gz", hash = "sha256:32fbe1538a437da160fa4e4477270bfdcd8876e2e364d0d12898302644496231", size = 5914 } wheels = [ { url = "https://files.pythonhosted.org/packages/de/9e/0efa8ecac772ad87a5674f8f8eb8e5939e45e95f48e7efa18415b160cd80/readme-0.7.1-py2.py3-none-any.whl", hash = "sha256:37482f34fc20bff7e4ad8a42f726dc902250d27a52e1196bb8fad4bdcfdcbbe4", size = 2988 }, ] +[[package]] +name = "readme-renderer" +version = "43.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.9'", +] +dependencies = [ + { name = "docutils", version = "0.20.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "nh3", marker = "python_full_version < '3.9'" }, + { name = "pygments", marker = "python_full_version < '3.9'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fe/b5/536c775084d239df6345dccf9b043419c7e3308bc31be4c7882196abc62e/readme_renderer-43.0.tar.gz", hash = "sha256:1818dd28140813509eeed8d62687f7cd4f7bad90d4db586001c5dc09d4fde311", size = 31768 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/45/be/3ea20dc38b9db08387cf97997a85a7d51527ea2057d71118feb0aa8afa55/readme_renderer-43.0-py3-none-any.whl", hash = "sha256:19db308d86ecd60e5affa3b2a98f017af384678c63c88e5d4556a380e674f3f9", size = 13301 }, +] + [[package]] name = "readme-renderer" version = "44.0" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.13'", + "python_full_version >= '3.9' and python_full_version < '3.13'", +] dependencies = [ - { name = "docutils" }, - { name = "nh3" }, - { name = "pygments" }, + { name = "docutils", version = "0.21.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "nh3", marker = "python_full_version >= '3.9'" }, + { name = "pygments", marker = "python_full_version >= '3.9'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/5a/a9/104ec9234c8448c4379768221ea6df01260cd6c2ce13182d4eac531c8342/readme_renderer-44.0.tar.gz", hash = "sha256:8712034eabbfa6805cacf1402b4eeb2a73028f72d1166d6f5cb7f9c047c5d1e1", size = 32056 } wheels = [ @@ -909,27 +1391,67 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c6/e6/3d6ec3bc3d254e7f005c543a661a41c3e788976d0e52a1ada195bd664344/ruff-0.9.4-py3-none-win_arm64.whl", hash = "sha256:585792f1e81509e38ac5123492f8875fbc36f3ede8185af0a26df348e5154f41", size = 10078251 }, ] +[[package]] +name = "selenium" +version = "4.27.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.9'", +] +dependencies = [ + { name = "certifi", marker = "python_full_version < '3.9'" }, + { name = "trio", version = "0.27.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "trio-websocket", marker = "python_full_version < '3.9'" }, + { name = "typing-extensions", marker = "python_full_version < '3.9'" }, + { name = "urllib3", version = "2.2.3", source = { registry = "https://pypi.org/simple" }, extra = ["socks"], marker = "python_full_version < '3.9'" }, + { name = "websocket-client", marker = "python_full_version < '3.9'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/44/8c/62c47c91072aa03af1c3b7d7f1c59b987db41c9fec0f158fb03a0da51aa6/selenium-4.27.1.tar.gz", hash = "sha256:5296c425a75ff1b44d0d5199042b36a6d1ef76c04fb775b97b40be739a9caae2", size = 973526 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a6/1e/5f1a5dd2a28528c4b3ec6e076b58e4c035810c805328f9936123283ca14e/selenium-4.27.1-py3-none-any.whl", hash = "sha256:b89b1f62b5cfe8025868556fe82360d6b649d464f75d2655cb966c8f8447ea18", size = 9707007 }, +] + [[package]] name = "selenium" version = "4.28.1" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.13'", + "python_full_version >= '3.9' and python_full_version < '3.13'", +] dependencies = [ - { name = "certifi" }, - { name = "trio" }, - { name = "trio-websocket" }, - { name = "typing-extensions" }, - { name = "urllib3", extra = ["socks"] }, - { name = "websocket-client" }, + { name = "certifi", marker = "python_full_version >= '3.9'" }, + { name = "trio", version = "0.28.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "trio-websocket", marker = "python_full_version >= '3.9'" }, + { name = "typing-extensions", marker = "python_full_version >= '3.9'" }, + { name = "urllib3", version = "2.3.0", source = { registry = "https://pypi.org/simple" }, extra = ["socks"], marker = "python_full_version >= '3.9'" }, + { name = "websocket-client", marker = "python_full_version >= '3.9'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/88/38/d62d4e8da649ad699b02eb1e95c3cfc20ff400744b9417b9093c5daebd4b/selenium-4.28.1.tar.gz", hash = "sha256:0072d08670d7ec32db901bd0107695a330cecac9f196e3afb3fa8163026e022a", size = 981633 } wheels = [ { url = "https://files.pythonhosted.org/packages/a0/9f/34d0ec09b0dd6fb7b08b93eb4b7b80049e0b9db0ba7f81ad814c9be78b8f/selenium-4.28.1-py3-none-any.whl", hash = "sha256:4238847e45e24e4472cfcf3554427512c7aab9443396435b1623ef406fff1cc1", size = 9530373 }, ] +[[package]] +name = "setuptools" +version = "75.3.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.9'", +] +sdist = { url = "https://files.pythonhosted.org/packages/ed/22/a438e0caa4576f8c383fa4d35f1cc01655a46c75be358960d815bfbb12bd/setuptools-75.3.0.tar.gz", hash = "sha256:fba5dd4d766e97be1b1681d98712680ae8f2f26d7881245f2ce9e40714f1a686", size = 1351577 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/90/12/282ee9bce8b58130cb762fbc9beabd531549952cac11fc56add11dcb7ea0/setuptools-75.3.0-py3-none-any.whl", hash = "sha256:f2504966861356aa38616760c0f66568e535562374995367b4e69c7143cf6bcd", size = 1251070 }, +] + [[package]] name = "setuptools" version = "75.8.0" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.13'", + "python_full_version >= '3.9' and python_full_version < '3.13'", +] sdist = { url = "https://files.pythonhosted.org/packages/92/ec/089608b791d210aec4e7f97488e67ab0d33add3efccb83a056cbafe3a2a6/setuptools-75.8.0.tar.gz", hash = "sha256:c5afc8f407c626b8313a86e10311dd3f661c6cd9c09d4bf8c15c0e11f9f2b0e6", size = 1343222 } wheels = [ { url = "https://files.pythonhosted.org/packages/69/8a/b9dc7678803429e4a3bc9ba462fa3dd9066824d3c607490235c6a796be5a/setuptools-75.8.0-py3-none-any.whl", hash = "sha256:e3982f444617239225d675215d51f6ba05f845d4eec313da4418fdbb56fb27e3", size = 1228782 }, @@ -1018,11 +1540,15 @@ dependencies = [ { name = "cachetools" }, { name = "chardet" }, { name = "colorama" }, - { name = "filelock" }, + { name = "filelock", version = "3.16.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "filelock", version = "3.17.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, { name = "packaging" }, { name = "platformdirs" }, { name = "pluggy" }, - { name = "pyproject-api" }, + { name = "pyproject-api", version = "1.8.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "pyproject-api", version = "1.9.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "tomli", marker = "python_full_version < '3.11.0'" }, + { name = "typing-extensions", marker = "python_full_version < '3.11.0'" }, { name = "virtualenv" }, ] sdist = { url = "https://files.pythonhosted.org/packages/cf/7b/97f757e159983737bdd8fb513f4c263cd411a846684814ed5433434a1fa9/tox-4.24.1.tar.gz", hash = "sha256:083a720adbc6166fff0b7d1df9d154f9d00bfccb9403b8abf6bc0ee435d6a62e", size = 194742 } @@ -1030,17 +1556,43 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ab/04/b0d1c1b44c98583cab9eabb4acdba964fdf6b6c597c53cfb8870fd08cbbf/tox-4.24.1-py3-none-any.whl", hash = "sha256:57ba7df7d199002c6df8c2db9e6484f3de6ca8f42013c083ea2d4d1e5c6bdc75", size = 171829 }, ] +[[package]] +name = "trio" +version = "0.27.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.9'", +] +dependencies = [ + { name = "attrs", marker = "python_full_version < '3.9'" }, + { name = "cffi", marker = "python_full_version < '3.9' and implementation_name != 'pypy' and os_name == 'nt'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.9'" }, + { name = "idna", marker = "python_full_version < '3.9'" }, + { name = "outcome", marker = "python_full_version < '3.9'" }, + { name = "sniffio", marker = "python_full_version < '3.9'" }, + { name = "sortedcontainers", marker = "python_full_version < '3.9'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/17/d1/a83dee5be404da7afe5a71783a33b8907bacb935a6dc8c69ab785e4a3eed/trio-0.27.0.tar.gz", hash = "sha256:1dcc95ab1726b2da054afea8fd761af74bad79bd52381b84eae408e983c76831", size = 568064 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/83/ec3196c360afffbc5b342ead48d1eb7393dd74fa70bca75d33905a86f211/trio-0.27.0-py3-none-any.whl", hash = "sha256:68eabbcf8f457d925df62da780eff15ff5dc68fd6b367e2dde59f7aaf2a0b884", size = 481734 }, +] + [[package]] name = "trio" version = "0.28.0" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.13'", + "python_full_version >= '3.9' and python_full_version < '3.13'", +] dependencies = [ - { name = "attrs" }, - { name = "cffi", marker = "implementation_name != 'pypy' and os_name == 'nt'" }, - { name = "idna" }, - { name = "outcome" }, - { name = "sniffio" }, - { name = "sortedcontainers" }, + { name = "attrs", marker = "python_full_version >= '3.9'" }, + { name = "cffi", marker = "python_full_version >= '3.9' and implementation_name != 'pypy' and os_name == 'nt'" }, + { name = "exceptiongroup", marker = "python_full_version >= '3.9' and python_full_version < '3.11.0'" }, + { name = "idna", marker = "python_full_version >= '3.9'" }, + { name = "outcome", marker = "python_full_version >= '3.9'" }, + { name = "sniffio", marker = "python_full_version >= '3.9'" }, + { name = "sortedcontainers", marker = "python_full_version >= '3.9'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/b3/73/57efab729506a8d4b89814f1e356ec8f3369de0ed4fd7e7616974d09646d/trio-0.28.0.tar.gz", hash = "sha256:4e547896fe9e8a5658e54e4c7c5fa1db748cbbbaa7c965e7d40505b928c73c05", size = 580318 } wheels = [ @@ -1052,7 +1604,9 @@ name = "trio-websocket" version = "0.11.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "trio" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11.0'" }, + { name = "trio", version = "0.27.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "trio", version = "0.28.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, { name = "wsproto" }, ] sdist = { url = "https://files.pythonhosted.org/packages/dd/36/abad2385853077424a11b818d9fd8350d249d9e31d583cb9c11cd4c85eda/trio-websocket-0.11.1.tar.gz", hash = "sha256:18c11793647703c158b1f6e62de638acada927344d534e3c7628eedcb746839f", size = 26511 } @@ -1078,10 +1632,31 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0f/dd/84f10e23edd882c6f968c21c2434fe67bd4a528967067515feca9e611e5e/tzdata-2025.1-py2.py3-none-any.whl", hash = "sha256:7e127113816800496f027041c570f50bcd464a020098a3b6b199517772303639", size = 346762 }, ] +[[package]] +name = "urllib3" +version = "2.2.3" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.9'", +] +sdist = { url = "https://files.pythonhosted.org/packages/ed/63/22ba4ebfe7430b76388e7cd448d5478814d3032121827c12a2cc287e2260/urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9", size = 300677 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac", size = 126338 }, +] + +[package.optional-dependencies] +socks = [ + { name = "pysocks", marker = "python_full_version < '3.9'" }, +] + [[package]] name = "urllib3" version = "2.3.0" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.13'", + "python_full_version >= '3.9' and python_full_version < '3.13'", +] sdist = { url = "https://files.pythonhosted.org/packages/aa/63/e53da845320b757bf29ef6a9062f5c669fe997973f966045cb019c3f4b66/urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d", size = 307268 } wheels = [ { url = "https://files.pythonhosted.org/packages/c8/19/4ec628951a74043532ca2cf5d97b7b14863931476d117c471e8e2b1eb39f/urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df", size = 128369 }, @@ -1089,7 +1664,7 @@ wheels = [ [package.optional-dependencies] socks = [ - { name = "pysocks" }, + { name = "pysocks", marker = "python_full_version >= '3.9'" }, ] [[package]] @@ -1107,7 +1682,8 @@ version = "20.29.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "distlib" }, - { name = "filelock" }, + { name = "filelock", version = "3.16.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "filelock", version = "3.17.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, { name = "platformdirs" }, ] sdist = { url = "https://files.pythonhosted.org/packages/a7/ca/f23dcb02e161a9bba141b1c08aa50e8da6ea25e6d780528f1d385a3efe25/virtualenv-20.29.1.tar.gz", hash = "sha256:b8b8970138d32fb606192cb97f6cd4bb644fa486be9308fb9b63f81091b5dc35", size = 7658028 } @@ -1115,10 +1691,26 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/89/9b/599bcfc7064fbe5740919e78c5df18e5dceb0887e676256a1061bb5ae232/virtualenv-20.29.1-py3-none-any.whl", hash = "sha256:4e4cb403c0b0da39e13b46b1b2476e505cb0046b25f242bee80f62bf990b2779", size = 4282379 }, ] +[[package]] +name = "waitress" +version = "3.0.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.9'", +] +sdist = { url = "https://files.pythonhosted.org/packages/70/34/cb77e5249c433eb177a11ab7425056b32d3b57855377fa1e38b397412859/waitress-3.0.0.tar.gz", hash = "sha256:005da479b04134cdd9dd602d1ee7c49d79de0537610d653674cc6cbde222b8a1", size = 179393 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5b/a9/485c953a1ac4cb98c28e41fd2c7184072df36bbf99734a51d44d04176878/waitress-3.0.0-py3-none-any.whl", hash = "sha256:2a06f242f4ba0cc563444ca3d1998959447477363a2d7e9b8b4d75d35cfd1669", size = 56698 }, +] + [[package]] name = "waitress" version = "3.0.2" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.13'", + "python_full_version >= '3.9' and python_full_version < '3.13'", +] sdist = { url = "https://files.pythonhosted.org/packages/bf/cb/04ddb054f45faa306a230769e868c28b8065ea196891f09004ebace5b184/waitress-3.0.2.tar.gz", hash = "sha256:682aaaf2af0c44ada4abfb70ded36393f0e307f4ab9456a215ce0020baefc31f", size = 179901 } wheels = [ { url = "https://files.pythonhosted.org/packages/8d/57/a27182528c90ef38d82b636a11f606b0cbb0e17588ed205435f8affe3368/waitress-3.0.2-py3-none-any.whl", hash = "sha256:c56d67fd6e87c2ee598b76abdd4e96cfad1f24cacdea5078d382b1f9d7b5ed2e", size = 56232 }, @@ -1154,14 +1746,35 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5a/84/44687a29792a70e111c5c477230a72c4b957d88d16141199bf9acb7537a3/websocket_client-1.8.0-py3-none-any.whl", hash = "sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526", size = 58826 }, ] +[[package]] +name = "webtest" +version = "3.0.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.9'", +] +dependencies = [ + { name = "beautifulsoup4", marker = "python_full_version < '3.9'" }, + { name = "waitress", version = "3.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "webob", marker = "python_full_version < '3.9'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/20/7e/7534c43c97234d0b5c9f228bb9646c4611e0fa33c2cefeb2e968be96d27e/webtest-3.0.1.tar.gz", hash = "sha256:493b5c802f8948a65b5e3a1ad5b2524ee5e1ab60cd713d9a3da3b8da082c06fe", size = 79278 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2b/6d/075023456a2ff8e01ef07afa069563f0d1e1a2fd359d7dbd7672a5bf218a/WebTest-3.0.1-py3-none-any.whl", hash = "sha256:b3bc75d020d0576ee93a5f149666045e58fe2400ea5f0c214d7430d7d213d0d0", size = 32154 }, +] + [[package]] name = "webtest" version = "3.0.4" source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.13'", + "python_full_version >= '3.9' and python_full_version < '3.13'", +] dependencies = [ - { name = "beautifulsoup4" }, - { name = "waitress" }, - { name = "webob" }, + { name = "beautifulsoup4", marker = "python_full_version >= '3.9'" }, + { name = "waitress", version = "3.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "webob", marker = "python_full_version >= '3.9'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/26/c5/b25980d591b111f3898c27b140bc30977794157522a8da91f5bbb5de99b7/webtest-3.0.4.tar.gz", hash = "sha256:94778d19a37e5abd7388dad4d93874410ecced53a1739a8e5ff2dbcba1cfc0c4", size = 79395 } wheels = [ @@ -1197,3 +1810,27 @@ sdist = { url = "https://files.pythonhosted.org/packages/06/97/56a6f56ce44578a69 wheels = [ { url = "https://files.pythonhosted.org/packages/44/48/def306413b25c3d01753603b1a222a011b8621aed27cd7f89cbc27e6b0f4/xlwt-1.3.0-py2.py3-none-any.whl", hash = "sha256:a082260524678ba48a297d922cc385f58278b8aa68741596a87de01a9c628b2e", size = 99981 }, ] + +[[package]] +name = "zipp" +version = "3.20.2" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.9'", +] +sdist = { url = "https://files.pythonhosted.org/packages/54/bf/5c0000c44ebc80123ecbdddba1f5dcd94a5ada602a9c225d84b5aaa55e86/zipp-3.20.2.tar.gz", hash = "sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29", size = 24199 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/8b/5ba542fa83c90e09eac972fc9baca7a88e7e7ca4b221a89251954019308b/zipp-3.20.2-py3-none-any.whl", hash = "sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350", size = 9200 }, +] + +[[package]] +name = "zipp" +version = "3.21.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.9' and python_full_version < '3.13'", +] +sdist = { url = "https://files.pythonhosted.org/packages/3f/50/bad581df71744867e9468ebd0bcd6505de3b275e06f202c2cb016e3ff56f/zipp-3.21.0.tar.gz", hash = "sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4", size = 24545 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/1a/7e4798e9339adc931158c9d69ecc34f5e6791489d469f5e50ec15e35f458/zipp-3.21.0-py3-none-any.whl", hash = "sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931", size = 9630 }, +] From 9de2e9b781f951509005fe4708cc32f1dc9c2b10 Mon Sep 17 00:00:00 2001 From: Stefano Apostolico Date: Fri, 7 Feb 2025 22:37:19 +0100 Subject: [PATCH 03/14] updates CI --- .github/workflows/release.yml | 48 +++++++++++++++++++++++ .github/workflows/test.yml | 74 ++++++++++++++++++----------------- 2 files changed, 86 insertions(+), 36 deletions(-) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..f69be8eb --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,48 @@ +name: Release to PyPI +on: + push: + tags: ["*"] + +env: + dists-artifact-name: python-package-distributions + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Install the latest version of uv + uses: astral-sh/setup-uv@v5 + with: + enable-cache: true + cache-dependency-glob: "pyproject.toml" + github-token: ${{ secrets.GITHUB_TOKEN }} + - name: Build package + run: uv build --python 3.13 --python-preference only-managed --sdist --wheel . --out-dir dist + - name: Store the distribution packages + uses: actions/upload-artifact@v4 + with: + name: ${{ env.dists-artifact-name }} + path: dist/* + + release: + needs: + - build + runs-on: ubuntu-latest + environment: + name: release + url: https://pypi.org/project/pytest-echo/${{ github.ref_name }} + permissions: + id-token: write + steps: + - name: Download all the dists + uses: actions/download-artifact@v4 + with: + name: ${{ env.dists-artifact-name }} + path: dist/ + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@v1.12.4 + with: + attestations: true diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 851f8562..941c65b7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,11 +1,13 @@ name: Test on: + workflow_dispatch: push: - branches: - - master - - develop + branches: [ "develop" ] + tags-ignore: [ "**" ] pull_request: + schedule: + - cron: "0 8 * * *" jobs: lint: @@ -30,9 +32,9 @@ jobs: strategy: fail-fast: false matrix: -# python-version: [ "3.10", "3.11", "3.12" ] -# django-version: [ "3.2", "4.2", "5.0" ] - python-version: [ "312" ] + # python-version: [ "3.10", "3.11", "3.12" ] + # django-version: [ "3.2", "4.2", "5.0" ] + python-version: [ "312" ] django-version: [ "51" ] env: PY_VER: ${{ matrix.python-version}} @@ -40,37 +42,37 @@ jobs: CELERY_BROKER_URL: redis://redis:6379/0 CELERY_ALWAYS_EAGER: true steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Install the latest version of uv - uses: astral-sh/setup-uv@v5 - with: - enable-cache: true - cache-dependency-glob: "pyproject.toml" - github-token: ${{ secrets.GITHUB_TOKEN }} + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Install the latest version of uv + uses: astral-sh/setup-uv@v5 + with: + enable-cache: true + cache-dependency-glob: "pyproject.toml" + github-token: ${{ secrets.GITHUB_TOKEN }} - - name: Install tox - run: uv tool install --python-preference only-managed --python 3.13 tox --with tox-uv + - name: Install tox + run: uv tool install --python-preference only-managed --python 3.13 tox --with tox-uv - - name: Install Python - if: matrix.python-version != '3.13' - run: uv python install --python-preference only-managed ${{ matrix.python-version}} + - name: Install Python + if: matrix.python-version != '3.13' + run: uv python install --python-preference only-managed ${{ matrix.python-version}} - - name: Setup test suite ${{ env.DJ_VER }}-${{ env.PY_VER }} - run: tox run -vv --notest --skip-missing-interpreters false -e d${{ env.DJ_VER }}-py${{ env.PY_VER }} + - name: Setup test suite ${{ env.DJ_VER }}-${{ env.PY_VER }} + run: tox run -vv --notest --skip-missing-interpreters false -e d${{ env.DJ_VER }}-py${{ env.PY_VER }} - - name: Run test suite - run: - COV_CMD=$(if [${{ env.DJ_VER }}-${{ env.PY_VER }}} == 51-312 ]; then echo "--cov=pytest_echo --cov-report=xml"; else echo ; fi) - tox run --skip-pkg-install -e d${{ env.DJ_VER }}-py${{ env.PY_VER }} $COV_CMD - env: - PYTEST_ADDOPTS: "-vv --durations=20" - DIFF_AGAINST: HEAD - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v5 - if: ${{ success() && matrix.python-version == 3.13 }} - with: - env_vars: OS - name: codecov-pytest-order - token: ${{ secrets.CODECOV_TOKEN }} + - name: Run test suite + run: + COV_CMD=$(if [${{ env.DJ_VER }}-${{ env.PY_VER }} == 51-312 ]; then echo "--cov=pytest_echo --cov-report=xml"; else echo ; fi) + tox run --skip-pkg-install -e d${{ env.DJ_VER }}-py${{ env.PY_VER }} $COV_CMD + env: + PYTEST_ADDOPTS: "-vv --durations=20" + DIFF_AGAINST: HEAD + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v5 + if: ${{ success() && matrix.python-version == 3.13 }} + with: + env_vars: OS + name: codecov-pytest-order + token: ${{ secrets.CODECOV_TOKEN }} From ffcbb30976e1a04a2ed0ebf31d343e93bb6c4357 Mon Sep 17 00:00:00 2001 From: Stefano Apostolico Date: Fri, 7 Feb 2025 22:44:11 +0100 Subject: [PATCH 04/14] add pre-commit config --- .gitignore | 2 +- .pre-commit-config.yaml | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 .pre-commit-config.yaml diff --git a/.gitignore b/.gitignore index 237793c6..a0b41752 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,6 @@ src/adminactions/version.py /docs/build /MANIFEST coverage.xml -sonar-project.properties .venv/ uv.lock +!.pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..8a00b0a7 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,35 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: end-of-file-fixer + - id: trailing-whitespace + - repo: https://github.com/python-jsonschema/check-jsonschema + rev: 0.31.0 + hooks: + - id: check-github-workflows + args: [ "--verbose" ] + - repo: https://github.com/tox-dev/tox-ini-fmt + rev: "1.5.0" + hooks: + - id: tox-ini-fmt + args: [ "-p", "lint" ] + - repo: https://github.com/tox-dev/pyproject-fmt + rev: "v2.5.0" + hooks: + - id: pyproject-fmt + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: "v0.9.4" + hooks: + - id: ruff-format + - id: ruff + args: [ "--fix", "--unsafe-fixes", "--exit-non-zero-on-fix" ] + - repo: https://github.com/adamchainz/djade-pre-commit + rev: "1.3.2" + hooks: + - id: djade + args: [ --target-version, "5.1" ] # Replace with Django version + - repo: meta + hooks: + - id: check-hooks-apply + - id: check-useless-excludes From c7a4effaa6fde67db3aa3f5739ebbab213883d05 Mon Sep 17 00:00:00 2001 From: Stefano Apostolico Date: Fri, 7 Feb 2025 23:04:30 +0100 Subject: [PATCH 05/14] updates CI --- .github/workflows/test.yml | 4 ++-- .gitignore | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 941c65b7..18f133b3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -63,8 +63,8 @@ jobs: run: tox run -vv --notest --skip-missing-interpreters false -e d${{ env.DJ_VER }}-py${{ env.PY_VER }} - name: Run test suite - run: - COV_CMD=$(if [${{ env.DJ_VER }}-${{ env.PY_VER }} == 51-312 ]; then echo "--cov=pytest_echo --cov-report=xml"; else echo ; fi) + run: | + COV_CMD=$(if [ ${{ env.DJ_VER }}-${{ env.PY_VER }} == 51-312 ]; then echo "--cov=pytest_echo --cov-report=xml"; else echo ; fi) tox run --skip-pkg-install -e d${{ env.DJ_VER }}-py${{ env.PY_VER }} $COV_CMD env: PYTEST_ADDOPTS: "-vv --durations=20" diff --git a/.gitignore b/.gitignore index a0b41752..e64c35cb 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ coverage.xml .venv/ uv.lock !.pre-commit-config.yaml +!.github/** From 6be8a4bfa4f6e0a94bffd8a207093646962e339e Mon Sep 17 00:00:00 2001 From: Stefano Apostolico Date: Fri, 7 Feb 2025 23:13:44 +0100 Subject: [PATCH 06/14] updates CI --- .github/workflows/test.yml | 4 ++-- .gitignore | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 18f133b3..e92858e9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -63,9 +63,9 @@ jobs: run: tox run -vv --notest --skip-missing-interpreters false -e d${{ env.DJ_VER }}-py${{ env.PY_VER }} - name: Run test suite +# COV_CMD=$(if [ ${{ env.DJ_VER }}-${{ env.PY_VER }} == 51-312 ]; then echo "--cov=pytest_echo --cov-report=xml"; else echo ; fi) run: | - COV_CMD=$(if [ ${{ env.DJ_VER }}-${{ env.PY_VER }} == 51-312 ]; then echo "--cov=pytest_echo --cov-report=xml"; else echo ; fi) - tox run --skip-pkg-install -e d${{ env.DJ_VER }}-py${{ env.PY_VER }} $COV_CMD + tox run --skip-pkg-install -e d${{ env.DJ_VER }}-py${{ env.PY_VER }} env: PYTEST_ADDOPTS: "-vv --durations=20" DIFF_AGAINST: HEAD diff --git a/.gitignore b/.gitignore index e64c35cb..2d0f92bb 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,6 @@ coverage.xml .venv/ uv.lock !.pre-commit-config.yaml -!.github/** +!.github +!.gitignore +!.coveragerc From 07131499bc89af383e67e39f4bc51305a3878b94 Mon Sep 17 00:00:00 2001 From: Stefano Apostolico Date: Fri, 7 Feb 2025 23:17:01 +0100 Subject: [PATCH 07/14] updates CI --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 3d82d260..ccaed7b5 100644 --- a/tox.ini +++ b/tox.ini @@ -14,7 +14,7 @@ wheel_build_env = .pkg deps = d32: django==3.2.* d42: django==4.2.* - d50: django==5.0.* + d51: django==5.1.* pypy: psycopg2cffi pass_env = CELERY_BROKER_URL From 144241ac3f057b5d76e9498a6cec0812180b255b Mon Sep 17 00:00:00 2001 From: Stefano Apostolico Date: Fri, 7 Feb 2025 23:28:22 +0100 Subject: [PATCH 08/14] updates CI --- pyproject.toml | 4 +--- tox.ini | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index b95de619..88c2d4cb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -148,9 +148,7 @@ max_supported_python = "3.13" [tool.pytest.ini_options] django_find_project = false norecursedirs = [ "demo", ".tox" ] -addopts = "--doctest-modules --tb=short --reuse-db --cov=adminactions --cov-report=html --cov-config=tests/.coveragerc --capture=no --doctest-glob=adminactions/*.py" -echo-version = [ "django" ] - +addopts = "--doctest-modules --echo-attr=django.conf.settings.DATABASES.default.ENGINE --tb=short --reuse-db --cov=adminactions --cov-report=html --cov-config=tests/.coveragerc --capture=no --doctest-glob=adminactions/*.py" python_files = "tests/test_*.py tests/**/test_*.py" markers = [ "functional: mark a test as functional", diff --git a/tox.ini b/tox.ini index ccaed7b5..6443866c 100644 --- a/tox.ini +++ b/tox.ini @@ -22,7 +22,7 @@ pass_env = set_env = CELERY_ALWAYS_EAGER = 1 CRYPTOGRAPHY_DONT_BUILD_RUST = 1 - DATABASE_URL = postgres://postgres:postgres@127.0.0.1:5432/adminactions + DATABASE_URL = sqlite:///adminactions.sqlite PYTHONDONTWRITEBYTECODE = true PYTHONPATH = ./src:./tests commands = From 308f833ef88071db21ec176ddff38317e181935d Mon Sep 17 00:00:00 2001 From: Stefano Apostolico Date: Sat, 8 Feb 2025 11:06:22 +0100 Subject: [PATCH 09/14] epand CI matrix and updateds README --- .github/workflows/test.yml | 6 ++---- README.md | 2 ++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e92858e9..7088340a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -32,10 +32,8 @@ jobs: strategy: fail-fast: false matrix: - # python-version: [ "3.10", "3.11", "3.12" ] - # django-version: [ "3.2", "4.2", "5.0" ] - python-version: [ "312" ] - django-version: [ "51" ] + python-version: [ "3.10", "3.11", "3.12" ] + django-version: [ "3.2", "4.2", "5.0" ] env: PY_VER: ${{ matrix.python-version}} DJ_VER: ${{ matrix.django-version}} diff --git a/README.md b/README.md index 65bd574c..7f397784 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ [![coverage](https://codecov.io/github/saxix/django-adminactions/coverage.svg?branch=develop)](https://codecov.io/github/saxix/django-adminactions?branch=develop) [![Test](https://github.com/saxix/django-adminactions/actions/workflows/test.yml/badge.svg)](https://github.com/saxix/django-adminactions/actions/workflows/test.yml) [![Docs](https://readthedocs.org/projects/django-adminactions/badge/?version=latest)](https://django-adminactions.readthedocs.io/en/latest/) +[![Django](https://img.shields.io/pypi/frameworkversions/django/django-adminactions)](https://pypi.org/project/django-adminactions/) + Collection of useful actions to use with django.contrib.admin.ModelAdmin and/or django.contrib.admin.AdminSite From 52fc5f523aadbf2d4e3d70400efae198726934e4 Mon Sep 17 00:00:00 2001 From: Stefano Apostolico Date: Mon, 10 Feb 2025 20:39:32 +0100 Subject: [PATCH 10/14] add tests --- pyproject.toml | 38 +- src/adminactions/__init__.py | 5 + src/adminactions/helpers.py | 2 +- .../adminactions/helpers/import_fixture.html | 27 +- src/adminactions/templatetags/massupdate.py | 2 +- tests/.coveragerc | 30 - tests/conftest.py | 17 +- tests/test_checks.py | 8 + .../test_create_extra_permissions_handler.py | 23 + tests/test_helpers.py | 28 + tests/test_version.py | 7 + tox.ini | 6 +- uv.lock | 679 ++---------------- 13 files changed, 207 insertions(+), 665 deletions(-) delete mode 100644 tests/.coveragerc create mode 100644 tests/test_checks.py create mode 100644 tests/test_create_extra_permissions_handler.py create mode 100644 tests/test_helpers.py create mode 100644 tests/test_version.py diff --git a/pyproject.toml b/pyproject.toml index 88c2d4cb..ce3d0f1c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,6 +50,7 @@ urls.Homepage = "https://github.com/saxix/django-adminactions" dev = [ "celery", "check-manifest", + "covdefaults>=2.3", "django-admin-extra-urls", "django-dynamic-fixture", "django-environ", @@ -148,13 +149,46 @@ max_supported_python = "3.13" [tool.pytest.ini_options] django_find_project = false norecursedirs = [ "demo", ".tox" ] -addopts = "--doctest-modules --echo-attr=django.conf.settings.DATABASES.default.ENGINE --tb=short --reuse-db --cov=adminactions --cov-report=html --cov-config=tests/.coveragerc --capture=no --doctest-glob=adminactions/*.py" -python_files = "tests/test_*.py tests/**/test_*.py" +addopts = "--doctest-modules --echo-attr=django.conf.settings.DATABASES.default.ENGINE --tb=short --reuse-db --capture=no --doctest-glob=adminactions/*.py" +python_files = "tests/test_*.py tests/**/test_*.py src/*.py" markers = [ "functional: mark a test as functional", "selenium: selenium test", "skip: skip test", ] +testpaths = [ + "src", + "tests", +] + +[tool.coverage] +run.source = [ + "adminactions", +] +run.dynamic_context = "test_function" +run.branch = true +run.parallel = true +run.omit = [ + "**/create_extra_permissions.py", +] +run.plugins = [ + "covdefaults", +] +report.fail_under = 80 +report.show_missing = true +report.exclude_lines = [ + "pragma: no cover", +] +html.show_contexts = true +html.skip_covered = false +paths.source = [ + "src", + ".tox*/*/lib/python*/site-packages", + ".tox*/pypy*/site-packages", + ".tox*\\*\\Lib\\site-packages", + "*/src", + "*\\src", +] [tool.uv] package = true diff --git a/src/adminactions/__init__.py b/src/adminactions/__init__.py index d93a8a2a..8eda015b 100644 --- a/src/adminactions/__init__.py +++ b/src/adminactions/__init__.py @@ -1,3 +1,8 @@ # VERSION = __version__ = "2.3.0" # NAME = "django-adminactions" # default_app_config = "adminactions.apps.Config" +from .version import __version__ + +__all__ = [ + "__version__", +] diff --git a/src/adminactions/helpers.py b/src/adminactions/helpers.py index b7634899..5d779fcb 100644 --- a/src/adminactions/helpers.py +++ b/src/adminactions/helpers.py @@ -52,7 +52,7 @@ def import_fixture(modeladmin: "ModelAdmin", request: "HttpRequest") -> "HttpRes obj.save() imported += 1 - modeladmin.message_user(request, imported, messages.SUCCESS) + modeladmin.message_user(request, f"{imported} objects imported", messages.SUCCESS) except Exception as e: modeladmin.message_user(request, f"{e.__class__.__name__}: {e}", messages.ERROR) diff --git a/src/adminactions/templates/adminactions/helpers/import_fixture.html b/src/adminactions/templates/adminactions/helpers/import_fixture.html index 843bc834..267d9d57 100644 --- a/src/adminactions/templates/adminactions/helpers/import_fixture.html +++ b/src/adminactions/templates/adminactions/helpers/import_fixture.html @@ -1,20 +1,15 @@ -{% extends "admin_extra_urls/action_page.html" %}{% load i18n static admin_list -admin_urls %} {% block breadcrumbs-items %} +{% extends "admin_extra_urls/action_page.html" %}{% load admin_list admin_urls i18n static %} {% block breadcrumbs-items %} {% translate 'Home' %} -› -{{ opts.app_config.verbose_name }} -› -{{ opts.verbose_name_plural|capfirst }} -{% if original %} › -{{ original }} -{% endif %} {% block breadcrumbs-active %}› {{ -action|default_if_none:title }} {% endblock breadcrumbs-active %} {% endblock -breadcrumbs-items %} {% block action-content %} -
    +› {{ opts.app_config.verbose_name }} +› {{ opts.verbose_name_plural|capfirst }} +{% if original %} + › {{ original }} +{% endif %} +{% block breadcrumbs-active %}› {{ action|default_if_none:title }} {% endblock %} +{% endblock breadcrumbs-items %} + +{% block action-content %} + {% csrf_token %} {{ form }} diff --git a/src/adminactions/templatetags/massupdate.py b/src/adminactions/templatetags/massupdate.py index f4c2aad2..6172aaa6 100644 --- a/src/adminactions/templatetags/massupdate.py +++ b/src/adminactions/templatetags/massupdate.py @@ -45,7 +45,7 @@ def link_fields_values(d: dict[str, list[tuple[int, str]]], field_name: str) -> value, label = el, el if label == "": # ignore empty - continue + continue # pragma: no cover ret.append( ' DjangoTestApp: ... + logger = logging.getLogger("test") @@ -116,12 +123,8 @@ def create_aa_permissions(db) -> None: @pytest.fixture -def app(request): - wtm = django_webtest.WebTestMixin() - wtm.csrf_checks = False - wtm._patch_settings() - request.addfinalizer(wtm._unpatch_settings) - return django_webtest.DjangoTestApp() +def app(request, django_app_factory: "AppFactory") -> DjangoTestApp: + return django_app_factory(csrf_checks=False) @pytest.fixture diff --git a/tests/test_checks.py b/tests/test_checks.py new file mode 100644 index 00000000..b377de3d --- /dev/null +++ b/tests/test_checks.py @@ -0,0 +1,8 @@ +from unittest.mock import Mock + + +def test_checks(): + from adminactions.checks import check_adminactions_settings + + errs = check_adminactions_settings(Mock()) + assert errs == [] diff --git a/tests/test_create_extra_permissions_handler.py b/tests/test_create_extra_permissions_handler.py new file mode 100644 index 00000000..257cdd7c --- /dev/null +++ b/tests/test_create_extra_permissions_handler.py @@ -0,0 +1,23 @@ +from unittest import mock +from unittest.mock import Mock + +import pytest +from django.apps import apps + +from adminactions import consts +from adminactions.apps import Config +from adminactions.models import create_extra_permissions_handler + + +@pytest.mark.parametrize("value", [consts.AA_PERMISSION_CREATE_USE_SIGNAL, consts.AA_PERMISSION_CREATE_USE_APPCONFIG]) +def test_post_migrate(value): + with mock.patch("adminactions.config.AA_PERMISSION_HANDLER", value): + create_extra_permissions_handler(Mock()) + + +def test_app_config(): + with mock.patch("adminactions.config.AA_PERMISSION_HANDLER", consts.AA_PERMISSION_CREATE_USE_APPCONFIG): + with mock.patch("adminactions.perms.create_extra_permissions") as m: + apps.get_app_config('adminactions').ready() + + assert m.call_count == 1 diff --git a/tests/test_helpers.py b/tests/test_helpers.py new file mode 100644 index 00000000..5c827057 --- /dev/null +++ b/tests/test_helpers.py @@ -0,0 +1,28 @@ +from pathlib import Path + +import pytest +from django.contrib.auth.models import User +from django.urls.base import reverse +from django_webtest import DjangoTestApp +from webtest import Upload + + +def test_import_fixture_by_content(app: DjangoTestApp, admin_user: User) -> None: + fixtures = Path(__file__).parent / "demo" / "fixtures" / "demoproject.json" + url = reverse("admin:demo_demomodel_changelist") + res = app.get(url, user=admin_user) + res = res.click("Import Fixture") + res.forms["import-form"]["fixture_content"] = fixtures.read_text() + res = res.forms["import-form"].submit() + assert "3 objects imported" in res.text + + +@pytest.mark.xfail(raises=AssertionError) +def test_import_fixture_by_file(app: DjangoTestApp, admin_user: User) -> None: + fixtures = Path(__file__).parent / "demo" / "fixtures" / "demoproject.json" + url = reverse("admin:demo_demomodel_changelist") + res = app.get(url, user=admin_user) + res = res.click("Import Fixture") + res.forms["import-form"]["fixture_file"] = Upload(str(fixtures)) + res = res.forms["import-form"].submit().follow() + assert "3 objects imported" in res.text diff --git a/tests/test_version.py b/tests/test_version.py new file mode 100644 index 00000000..e580f9d9 --- /dev/null +++ b/tests/test_version.py @@ -0,0 +1,7 @@ +from __future__ import annotations + +import adminactions + + +def test_version() -> None: + assert adminactions.__version__ is not None diff --git a/tox.ini b/tox.ini index 6443866c..cf89d46e 100644 --- a/tox.ini +++ b/tox.ini @@ -26,7 +26,11 @@ set_env = PYTHONDONTWRITEBYTECODE = true PYTHONPATH = ./src:./tests commands = - {posargs:pytest tests/ src --doctest-modules --create-db} + coverage erase + coverage run -m pytest --junitxml {toxworkdir}{/}junit.{envname}.xml {posargs:tests} + coverage combine + coverage report + coverage html -d {envtmpdir}{/}htmlcov dependency_groups = dev [testenv:lint] diff --git a/uv.lock b/uv.lock index 1a35e5eb..16b241e1 100644 --- a/uv.lock +++ b/uv.lock @@ -1,9 +1,8 @@ version = 1 -requires-python = ">=3.8" +requires-python = ">=3.9" resolution-markers = [ "python_full_version >= '3.13'", - "python_full_version >= '3.9' and python_full_version < '3.13'", - "python_full_version < '3.9'", + "python_full_version < '3.13'", ] [[package]] @@ -45,24 +44,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fc/30/d4986a882011f9df997a55e6becd864812ccfcd821d64aac8570ee39f719/attrs-25.1.0-py3-none-any.whl", hash = "sha256:c75a69e28a550a7e93789579c22aa26b0f5b83b75dc4e08fe092980051e1090a", size = 63152 }, ] -[[package]] -name = "backports-zoneinfo" -version = "0.2.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ad/85/475e514c3140937cf435954f78dedea1861aeab7662d11de232bdaa90655/backports.zoneinfo-0.2.1.tar.gz", hash = "sha256:fadbfe37f74051d024037f223b8e001611eac868b5c5b06144ef4d8b799862f2", size = 74098 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4a/6d/eca004eeadcbf8bd64cc96feb9e355536147f0577420b44d80c7cac70767/backports.zoneinfo-0.2.1-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:8961c0f32cd0336fb8e8ead11a1f8cd99ec07145ec2931122faaac1c8f7fd987", size = 35816 }, - { url = "https://files.pythonhosted.org/packages/c1/8f/9b1b920a6a95652463143943fa3b8c000cb0b932ab463764a6f2a2416560/backports.zoneinfo-0.2.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e81b76cace8eda1fca50e345242ba977f9be6ae3945af8d46326d776b4cf78d1", size = 72147 }, - { url = "https://files.pythonhosted.org/packages/1a/ab/3e941e3fcf1b7d3ab3d0233194d99d6a0ed6b24f8f956fc81e47edc8c079/backports.zoneinfo-0.2.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7b0a64cda4145548fed9efc10322770f929b944ce5cee6c0dfe0c87bf4c0c8c9", size = 74033 }, - { url = "https://files.pythonhosted.org/packages/c0/34/5fdb0a3a28841d215c255be8fc60b8666257bb6632193c86fd04b63d4a31/backports.zoneinfo-0.2.1-cp38-cp38-win32.whl", hash = "sha256:1b13e654a55cd45672cb54ed12148cd33628f672548f373963b0bff67b217328", size = 36803 }, - { url = "https://files.pythonhosted.org/packages/78/cc/e27fd6493bbce8dbea7e6c1bc861fe3d3bc22c4f7c81f4c3befb8ff5bfaf/backports.zoneinfo-0.2.1-cp38-cp38-win_amd64.whl", hash = "sha256:4a0f800587060bf8880f954dbef70de6c11bbe59c673c3d818921f042f9954a6", size = 38967 }, -] - -[package.optional-dependencies] -tzdata = [ - { name = "tzdata", marker = "python_full_version < '3.9'" }, -] - [[package]] name = "beautifulsoup4" version = "4.13.3" @@ -91,11 +72,10 @@ version = "1.2.2.post1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "os_name == 'nt'" }, - { name = "importlib-metadata", version = "8.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "importlib-metadata", version = "8.6.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9' and python_full_version < '3.10.2'" }, + { name = "importlib-metadata", marker = "python_full_version < '3.10.2'" }, { name = "packaging" }, { name = "pyproject-hooks" }, - { name = "tomli", marker = "python_full_version < '3.11.0'" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/7d/46/aeab111f8e06793e4f0e421fcad593d547fb8313b50990f31681ee2fb1ad/build-1.2.2.post1.tar.gz", hash = "sha256:b36993e92ca9375a219c99e606a122ff365a760a2d4bba0caa09bd5278b608b7", size = 46701 } wheels = [ @@ -116,7 +96,6 @@ name = "celery" version = "5.4.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "backports-zoneinfo", marker = "python_full_version < '3.9'" }, { name = "billiard" }, { name = "click" }, { name = "click-didyoumean" }, @@ -158,8 +137,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/50/b9/db34c4755a7bd1cb2d1603ac3863f22bcecbd1ba29e5ee841a4bc510b294/cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", size = 181976 }, { url = "https://files.pythonhosted.org/packages/bf/ee/f94057fa6426481d663b88637a9a10e859e492c73d0384514a17d78ee205/cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", size = 172475 }, { url = "https://files.pythonhosted.org/packages/7c/fc/6a8cb64e5f0324877d503c854da15d76c1e50eb722e320b15345c4d0c6de/cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", size = 182009 }, - { url = "https://files.pythonhosted.org/packages/e2/63/2bed8323890cb613bbecda807688a31ed11a7fe7afe31f8faaae0206a9a3/cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8", size = 171576 }, - { url = "https://files.pythonhosted.org/packages/2f/70/80c33b044ebc79527447fd4fbc5455d514c3bb840dede4455de97da39b4d/cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1", size = 181229 }, { url = "https://files.pythonhosted.org/packages/cb/b5/fd9f8b5a84010ca169ee49f4e4ad6f8c05f4e3545b72ee041dbbcb159882/cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7", size = 171820 }, { url = "https://files.pythonhosted.org/packages/8c/52/b08750ce0bce45c143e1b5d7357ee8c55341b52bdef4b0f081af1eb248c2/cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662", size = 181290 }, ] @@ -179,9 +156,8 @@ version = "0.50" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "build" }, - { name = "setuptools", version = "75.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "setuptools", version = "75.8.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, - { name = "tomli", marker = "python_full_version < '3.11.0'" }, + { name = "setuptools" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/a8/ab/7607952f2c8d34c4124309dd3ea17c256fd3420a4ade01322daf9402b0b5/check_manifest-0.50.tar.gz", hash = "sha256:d300f9f292986aa1a30424af44eb45c5644e0a810e392e62d553b24bb3393494", size = 44827 } wheels = [ @@ -246,13 +222,22 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, ] +[[package]] +name = "covdefaults" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "coverage" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/44/ee/9a6f2611f72e4c5657ae5542a510cf4164d2c673687c0ea73bb1cbd85b4d/covdefaults-2.3.0.tar.gz", hash = "sha256:4e99f679f12d792bc62e5510fa3eb59546ed47bd569e36e4fddc4081c9c3ebf7", size = 4835 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/4c/823bc951445aa97e5a1b7e337690db3abf85212c8d138e170922e7916ac8/covdefaults-2.3.0-py2.py3-none-any.whl", hash = "sha256:2832961f6ffcfe4b57c338bc3418a3526f495c26fb9c54565409c5532f7c41be", size = 5144 }, +] + [[package]] name = "coverage" version = "7.6.1" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.9'", -] sdist = { url = "https://files.pythonhosted.org/packages/f7/08/7e37f82e4d1aead42a7443ff06a1e406aabf7302c4f00a546e4b320b994c/coverage-7.6.1.tar.gz", hash = "sha256:953510dfb7b12ab69d20135a0662397f077c59b1e6379a768e97c59d852ee51d", size = 798791 } wheels = [ { url = "https://files.pythonhosted.org/packages/7e/61/eb7ce5ed62bacf21beca4937a90fe32545c91a3c8a42a30c6616d48fc70d/coverage-7.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b06079abebbc0e89e6163b8e8f0e16270124c154dc6e4a47b413dd538859af16", size = 206690 }, @@ -305,16 +290,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/52/76/1766bb8b803a88f93c3a2d07e30ffa359467810e5cbc68e375ebe6906efb/coverage-7.6.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:225667980479a17db1048cb2bf8bfb39b8e5be8f164b8f6628b64f78a72cf9d3", size = 247598 }, { url = "https://files.pythonhosted.org/packages/66/8b/f54f8db2ae17188be9566e8166ac6df105c1c611e25da755738025708d54/coverage-7.6.1-cp313-cp313t-win32.whl", hash = "sha256:170d444ab405852903b7d04ea9ae9b98f98ab6d7e63e1115e82620807519797f", size = 210307 }, { url = "https://files.pythonhosted.org/packages/9f/b0/e0dca6da9170aefc07515cce067b97178cefafb512d00a87a1c717d2efd5/coverage-7.6.1-cp313-cp313t-win_amd64.whl", hash = "sha256:b9f222de8cded79c49bf184bdbc06630d4c58eec9459b939b4a690c82ed05657", size = 211453 }, - { url = "https://files.pythonhosted.org/packages/81/d0/d9e3d554e38beea5a2e22178ddb16587dbcbe9a1ef3211f55733924bf7fa/coverage-7.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6db04803b6c7291985a761004e9060b2bca08da6d04f26a7f2294b8623a0c1a0", size = 206674 }, - { url = "https://files.pythonhosted.org/packages/38/ea/cab2dc248d9f45b2b7f9f1f596a4d75a435cb364437c61b51d2eb33ceb0e/coverage-7.6.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f1adfc8ac319e1a348af294106bc6a8458a0f1633cc62a1446aebc30c5fa186a", size = 207101 }, - { url = "https://files.pythonhosted.org/packages/ca/6f/f82f9a500c7c5722368978a5390c418d2a4d083ef955309a8748ecaa8920/coverage-7.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a95324a9de9650a729239daea117df21f4b9868ce32e63f8b650ebe6cef5595b", size = 236554 }, - { url = "https://files.pythonhosted.org/packages/a6/94/d3055aa33d4e7e733d8fa309d9adf147b4b06a82c1346366fc15a2b1d5fa/coverage-7.6.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b43c03669dc4618ec25270b06ecd3ee4fa94c7f9b3c14bae6571ca00ef98b0d3", size = 234440 }, - { url = "https://files.pythonhosted.org/packages/e4/6e/885bcd787d9dd674de4a7d8ec83faf729534c63d05d51d45d4fa168f7102/coverage-7.6.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8929543a7192c13d177b770008bc4e8119f2e1f881d563fc6b6305d2d0ebe9de", size = 235889 }, - { url = "https://files.pythonhosted.org/packages/f4/63/df50120a7744492710854860783d6819ff23e482dee15462c9a833cc428a/coverage-7.6.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:a09ece4a69cf399510c8ab25e0950d9cf2b42f7b3cb0374f95d2e2ff594478a6", size = 235142 }, - { url = "https://files.pythonhosted.org/packages/3a/5d/9d0acfcded2b3e9ce1c7923ca52ccc00c78a74e112fc2aee661125b7843b/coverage-7.6.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:9054a0754de38d9dbd01a46621636689124d666bad1936d76c0341f7d71bf569", size = 233805 }, - { url = "https://files.pythonhosted.org/packages/c4/56/50abf070cb3cd9b1dd32f2c88f083aab561ecbffbcd783275cb51c17f11d/coverage-7.6.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0dbde0f4aa9a16fa4d754356a8f2e36296ff4d83994b2c9d8398aa32f222f989", size = 234655 }, - { url = "https://files.pythonhosted.org/packages/25/ee/b4c246048b8485f85a2426ef4abab88e48c6e80c74e964bea5cd4cd4b115/coverage-7.6.1-cp38-cp38-win32.whl", hash = "sha256:da511e6ad4f7323ee5702e6633085fb76c2f893aaf8ce4c51a0ba4fc07580ea7", size = 209296 }, - { url = "https://files.pythonhosted.org/packages/5c/1c/96cf86b70b69ea2b12924cdf7cabb8ad10e6130eab8d767a1099fbd2a44f/coverage-7.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:3f1156e3e8f2872197af3840d8ad307a9dd18e615dc64d9ee41696f287c57ad8", size = 210137 }, { url = "https://files.pythonhosted.org/packages/19/d3/d54c5aa83268779d54c86deb39c1c4566e5d45c155369ca152765f8db413/coverage-7.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:abd5fd0db5f4dc9289408aaf34908072f805ff7792632250dcb36dc591d24255", size = 206688 }, { url = "https://files.pythonhosted.org/packages/a5/fe/137d5dca72e4a258b1bc17bb04f2e0196898fe495843402ce826a7419fe3/coverage-7.6.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:547f45fa1a93154bd82050a7f3cddbc1a7a4dd2a9bf5cb7d06f4ae29fe94eaf8", size = 207120 }, { url = "https://files.pythonhosted.org/packages/78/5b/a0a796983f3201ff5485323b225d7c8b74ce30c11f456017e23d8e8d1945/coverage-7.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:645786266c8f18a931b65bfcefdbf6952dd0dea98feee39bd188607a9d307ed2", size = 235249 }, @@ -330,85 +305,7 @@ wheels = [ [package.optional-dependencies] toml = [ - { name = "tomli", marker = "python_full_version < '3.9'" }, -] - -[[package]] -name = "coverage" -version = "7.6.10" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.13'", - "python_full_version >= '3.9' and python_full_version < '3.13'", -] -sdist = { url = "https://files.pythonhosted.org/packages/84/ba/ac14d281f80aab516275012e8875991bb06203957aa1e19950139238d658/coverage-7.6.10.tar.gz", hash = "sha256:7fb105327c8f8f0682e29843e2ff96af9dcbe5bab8eeb4b398c6a33a16d80a23", size = 803868 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c5/12/2a2a923edf4ddabdffed7ad6da50d96a5c126dae7b80a33df7310e329a1e/coverage-7.6.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5c912978f7fbf47ef99cec50c4401340436d200d41d714c7a4766f377c5b7b78", size = 207982 }, - { url = "https://files.pythonhosted.org/packages/ca/49/6985dbca9c7be3f3cb62a2e6e492a0c88b65bf40579e16c71ae9c33c6b23/coverage-7.6.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a01ec4af7dfeb96ff0078ad9a48810bb0cc8abcb0115180c6013a6b26237626c", size = 208414 }, - { url = "https://files.pythonhosted.org/packages/35/93/287e8f1d1ed2646f4e0b2605d14616c9a8a2697d0d1b453815eb5c6cebdb/coverage-7.6.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3b204c11e2b2d883946fe1d97f89403aa1811df28ce0447439178cc7463448a", size = 236860 }, - { url = "https://files.pythonhosted.org/packages/de/e1/cfdb5627a03567a10031acc629b75d45a4ca1616e54f7133ca1fa366050a/coverage-7.6.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32ee6d8491fcfc82652a37109f69dee9a830e9379166cb73c16d8dc5c2915165", size = 234758 }, - { url = "https://files.pythonhosted.org/packages/6d/85/fc0de2bcda3f97c2ee9fe8568f7d48f7279e91068958e5b2cc19e0e5f600/coverage-7.6.10-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675cefc4c06e3b4c876b85bfb7c59c5e2218167bbd4da5075cbe3b5790a28988", size = 235920 }, - { url = "https://files.pythonhosted.org/packages/79/73/ef4ea0105531506a6f4cf4ba571a214b14a884630b567ed65b3d9c1975e1/coverage-7.6.10-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f4f620668dbc6f5e909a0946a877310fb3d57aea8198bde792aae369ee1c23b5", size = 234986 }, - { url = "https://files.pythonhosted.org/packages/c6/4d/75afcfe4432e2ad0405c6f27adeb109ff8976c5e636af8604f94f29fa3fc/coverage-7.6.10-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:4eea95ef275de7abaef630c9b2c002ffbc01918b726a39f5a4353916ec72d2f3", size = 233446 }, - { url = "https://files.pythonhosted.org/packages/86/5b/efee56a89c16171288cafff022e8af44f8f94075c2d8da563c3935212871/coverage-7.6.10-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e2f0280519e42b0a17550072861e0bc8a80a0870de260f9796157d3fca2733c5", size = 234566 }, - { url = "https://files.pythonhosted.org/packages/f2/db/67770cceb4a64d3198bf2aa49946f411b85ec6b0a9b489e61c8467a4253b/coverage-7.6.10-cp310-cp310-win32.whl", hash = "sha256:bc67deb76bc3717f22e765ab3e07ee9c7a5e26b9019ca19a3b063d9f4b874244", size = 210675 }, - { url = "https://files.pythonhosted.org/packages/8d/27/e8bfc43f5345ec2c27bc8a1fa77cdc5ce9dcf954445e11f14bb70b889d14/coverage-7.6.10-cp310-cp310-win_amd64.whl", hash = "sha256:0f460286cb94036455e703c66988851d970fdfd8acc2a1122ab7f4f904e4029e", size = 211518 }, - { url = "https://files.pythonhosted.org/packages/85/d2/5e175fcf6766cf7501a8541d81778fd2f52f4870100e791f5327fd23270b/coverage-7.6.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ea3c8f04b3e4af80e17bab607c386a830ffc2fb88a5484e1df756478cf70d1d3", size = 208088 }, - { url = "https://files.pythonhosted.org/packages/4b/6f/06db4dc8fca33c13b673986e20e466fd936235a6ec1f0045c3853ac1b593/coverage-7.6.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:507a20fc863cae1d5720797761b42d2d87a04b3e5aeb682ef3b7332e90598f43", size = 208536 }, - { url = "https://files.pythonhosted.org/packages/0d/62/c6a0cf80318c1c1af376d52df444da3608eafc913b82c84a4600d8349472/coverage-7.6.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d37a84878285b903c0fe21ac8794c6dab58150e9359f1aaebbeddd6412d53132", size = 240474 }, - { url = "https://files.pythonhosted.org/packages/a3/59/750adafc2e57786d2e8739a46b680d4fb0fbc2d57fbcb161290a9f1ecf23/coverage-7.6.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a534738b47b0de1995f85f582d983d94031dffb48ab86c95bdf88dc62212142f", size = 237880 }, - { url = "https://files.pythonhosted.org/packages/2c/f8/ef009b3b98e9f7033c19deb40d629354aab1d8b2d7f9cfec284dbedf5096/coverage-7.6.10-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d7a2bf79378d8fb8afaa994f91bfd8215134f8631d27eba3e0e2c13546ce994", size = 239750 }, - { url = "https://files.pythonhosted.org/packages/a6/e2/6622f3b70f5f5b59f705e680dae6db64421af05a5d1e389afd24dae62e5b/coverage-7.6.10-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6713ba4b4ebc330f3def51df1d5d38fad60b66720948112f114968feb52d3f99", size = 238642 }, - { url = "https://files.pythonhosted.org/packages/2d/10/57ac3f191a3c95c67844099514ff44e6e19b2915cd1c22269fb27f9b17b6/coverage-7.6.10-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ab32947f481f7e8c763fa2c92fd9f44eeb143e7610c4ca9ecd6a36adab4081bd", size = 237266 }, - { url = "https://files.pythonhosted.org/packages/ee/2d/7016f4ad9d553cabcb7333ed78ff9d27248ec4eba8dd21fa488254dff894/coverage-7.6.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7bbd8c8f1b115b892e34ba66a097b915d3871db7ce0e6b9901f462ff3a975377", size = 238045 }, - { url = "https://files.pythonhosted.org/packages/a7/fe/45af5c82389a71e0cae4546413266d2195c3744849669b0bab4b5f2c75da/coverage-7.6.10-cp311-cp311-win32.whl", hash = "sha256:299e91b274c5c9cdb64cbdf1b3e4a8fe538a7a86acdd08fae52301b28ba297f8", size = 210647 }, - { url = "https://files.pythonhosted.org/packages/db/11/3f8e803a43b79bc534c6a506674da9d614e990e37118b4506faf70d46ed6/coverage-7.6.10-cp311-cp311-win_amd64.whl", hash = "sha256:489a01f94aa581dbd961f306e37d75d4ba16104bbfa2b0edb21d29b73be83609", size = 211508 }, - { url = "https://files.pythonhosted.org/packages/86/77/19d09ea06f92fdf0487499283b1b7af06bc422ea94534c8fe3a4cd023641/coverage-7.6.10-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:27c6e64726b307782fa5cbe531e7647aee385a29b2107cd87ba7c0105a5d3853", size = 208281 }, - { url = "https://files.pythonhosted.org/packages/b6/67/5479b9f2f99fcfb49c0d5cf61912a5255ef80b6e80a3cddba39c38146cf4/coverage-7.6.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c56e097019e72c373bae32d946ecf9858fda841e48d82df7e81c63ac25554078", size = 208514 }, - { url = "https://files.pythonhosted.org/packages/15/d1/febf59030ce1c83b7331c3546d7317e5120c5966471727aa7ac157729c4b/coverage-7.6.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7827a5bc7bdb197b9e066cdf650b2887597ad124dd99777332776f7b7c7d0d0", size = 241537 }, - { url = "https://files.pythonhosted.org/packages/4b/7e/5ac4c90192130e7cf8b63153fe620c8bfd9068f89a6d9b5f26f1550f7a26/coverage-7.6.10-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:204a8238afe787323a8b47d8be4df89772d5c1e4651b9ffa808552bdf20e1d50", size = 238572 }, - { url = "https://files.pythonhosted.org/packages/dc/03/0334a79b26ecf59958f2fe9dd1f5ab3e2f88db876f5071933de39af09647/coverage-7.6.10-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e67926f51821b8e9deb6426ff3164870976fe414d033ad90ea75e7ed0c2e5022", size = 240639 }, - { url = "https://files.pythonhosted.org/packages/d7/45/8a707f23c202208d7b286d78ad6233f50dcf929319b664b6cc18a03c1aae/coverage-7.6.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e78b270eadb5702938c3dbe9367f878249b5ef9a2fcc5360ac7bff694310d17b", size = 240072 }, - { url = "https://files.pythonhosted.org/packages/66/02/603ce0ac2d02bc7b393279ef618940b4a0535b0868ee791140bda9ecfa40/coverage-7.6.10-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:714f942b9c15c3a7a5fe6876ce30af831c2ad4ce902410b7466b662358c852c0", size = 238386 }, - { url = "https://files.pythonhosted.org/packages/04/62/4e6887e9be060f5d18f1dd58c2838b2d9646faf353232dec4e2d4b1c8644/coverage-7.6.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:abb02e2f5a3187b2ac4cd46b8ced85a0858230b577ccb2c62c81482ca7d18852", size = 240054 }, - { url = "https://files.pythonhosted.org/packages/5c/74/83ae4151c170d8bd071924f212add22a0e62a7fe2b149edf016aeecad17c/coverage-7.6.10-cp312-cp312-win32.whl", hash = "sha256:55b201b97286cf61f5e76063f9e2a1d8d2972fc2fcfd2c1272530172fd28c359", size = 210904 }, - { url = "https://files.pythonhosted.org/packages/c3/54/de0893186a221478f5880283119fc40483bc460b27c4c71d1b8bba3474b9/coverage-7.6.10-cp312-cp312-win_amd64.whl", hash = "sha256:e4ae5ac5e0d1e4edfc9b4b57b4cbecd5bc266a6915c500f358817a8496739247", size = 211692 }, - { url = "https://files.pythonhosted.org/packages/25/6d/31883d78865529257bf847df5789e2ae80e99de8a460c3453dbfbe0db069/coverage-7.6.10-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:05fca8ba6a87aabdd2d30d0b6c838b50510b56cdcfc604d40760dae7153b73d9", size = 208308 }, - { url = "https://files.pythonhosted.org/packages/70/22/3f2b129cc08de00c83b0ad6252e034320946abfc3e4235c009e57cfeee05/coverage-7.6.10-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9e80eba8801c386f72e0712a0453431259c45c3249f0009aff537a517b52942b", size = 208565 }, - { url = "https://files.pythonhosted.org/packages/97/0a/d89bc2d1cc61d3a8dfe9e9d75217b2be85f6c73ebf1b9e3c2f4e797f4531/coverage-7.6.10-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a372c89c939d57abe09e08c0578c1d212e7a678135d53aa16eec4430adc5e690", size = 241083 }, - { url = "https://files.pythonhosted.org/packages/4c/81/6d64b88a00c7a7aaed3a657b8eaa0931f37a6395fcef61e53ff742b49c97/coverage-7.6.10-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ec22b5e7fe7a0fa8509181c4aac1db48f3dd4d3a566131b313d1efc102892c18", size = 238235 }, - { url = "https://files.pythonhosted.org/packages/9a/0b/7797d4193f5adb4b837207ed87fecf5fc38f7cc612b369a8e8e12d9fa114/coverage-7.6.10-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26bcf5c4df41cad1b19c84af71c22cbc9ea9a547fc973f1f2cc9a290002c8b3c", size = 240220 }, - { url = "https://files.pythonhosted.org/packages/65/4d/6f83ca1bddcf8e51bf8ff71572f39a1c73c34cf50e752a952c34f24d0a60/coverage-7.6.10-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4e4630c26b6084c9b3cb53b15bd488f30ceb50b73c35c5ad7871b869cb7365fd", size = 239847 }, - { url = "https://files.pythonhosted.org/packages/30/9d/2470df6aa146aff4c65fee0f87f58d2164a67533c771c9cc12ffcdb865d5/coverage-7.6.10-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2396e8116db77789f819d2bc8a7e200232b7a282c66e0ae2d2cd84581a89757e", size = 237922 }, - { url = "https://files.pythonhosted.org/packages/08/dd/723fef5d901e6a89f2507094db66c091449c8ba03272861eaefa773ad95c/coverage-7.6.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:79109c70cc0882e4d2d002fe69a24aa504dec0cc17169b3c7f41a1d341a73694", size = 239783 }, - { url = "https://files.pythonhosted.org/packages/3d/f7/64d3298b2baf261cb35466000628706ce20a82d42faf9b771af447cd2b76/coverage-7.6.10-cp313-cp313-win32.whl", hash = "sha256:9e1747bab246d6ff2c4f28b4d186b205adced9f7bd9dc362051cc37c4a0c7bd6", size = 210965 }, - { url = "https://files.pythonhosted.org/packages/d5/58/ec43499a7fc681212fe7742fe90b2bc361cdb72e3181ace1604247a5b24d/coverage-7.6.10-cp313-cp313-win_amd64.whl", hash = "sha256:254f1a3b1eef5f7ed23ef265eaa89c65c8c5b6b257327c149db1ca9d4a35f25e", size = 211719 }, - { url = "https://files.pythonhosted.org/packages/ab/c9/f2857a135bcff4330c1e90e7d03446b036b2363d4ad37eb5e3a47bbac8a6/coverage-7.6.10-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2ccf240eb719789cedbb9fd1338055de2761088202a9a0b73032857e53f612fe", size = 209050 }, - { url = "https://files.pythonhosted.org/packages/aa/b3/f840e5bd777d8433caa9e4a1eb20503495709f697341ac1a8ee6a3c906ad/coverage-7.6.10-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:0c807ca74d5a5e64427c8805de15b9ca140bba13572d6d74e262f46f50b13273", size = 209321 }, - { url = "https://files.pythonhosted.org/packages/85/7d/125a5362180fcc1c03d91850fc020f3831d5cda09319522bcfa6b2b70be7/coverage-7.6.10-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bcfa46d7709b5a7ffe089075799b902020b62e7ee56ebaed2f4bdac04c508d8", size = 252039 }, - { url = "https://files.pythonhosted.org/packages/a9/9c/4358bf3c74baf1f9bddd2baf3756b54c07f2cfd2535f0a47f1e7757e54b3/coverage-7.6.10-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4e0de1e902669dccbf80b0415fb6b43d27edca2fbd48c74da378923b05316098", size = 247758 }, - { url = "https://files.pythonhosted.org/packages/cf/c7/de3eb6fc5263b26fab5cda3de7a0f80e317597a4bad4781859f72885f300/coverage-7.6.10-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f7b444c42bbc533aaae6b5a2166fd1a797cdb5eb58ee51a92bee1eb94a1e1cb", size = 250119 }, - { url = "https://files.pythonhosted.org/packages/3e/e6/43de91f8ba2ec9140c6a4af1102141712949903dc732cf739167cfa7a3bc/coverage-7.6.10-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b330368cb99ef72fcd2dc3ed260adf67b31499584dc8a20225e85bfe6f6cfed0", size = 249597 }, - { url = "https://files.pythonhosted.org/packages/08/40/61158b5499aa2adf9e37bc6d0117e8f6788625b283d51e7e0c53cf340530/coverage-7.6.10-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:9a7cfb50515f87f7ed30bc882f68812fd98bc2852957df69f3003d22a2aa0abf", size = 247473 }, - { url = "https://files.pythonhosted.org/packages/50/69/b3f2416725621e9f112e74e8470793d5b5995f146f596f133678a633b77e/coverage-7.6.10-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6f93531882a5f68c28090f901b1d135de61b56331bba82028489bc51bdd818d2", size = 248737 }, - { url = "https://files.pythonhosted.org/packages/3c/6e/fe899fb937657db6df31cc3e61c6968cb56d36d7326361847440a430152e/coverage-7.6.10-cp313-cp313t-win32.whl", hash = "sha256:89d76815a26197c858f53c7f6a656686ec392b25991f9e409bcef020cd532312", size = 211611 }, - { url = "https://files.pythonhosted.org/packages/1c/55/52f5e66142a9d7bc93a15192eba7a78513d2abf6b3558d77b4ca32f5f424/coverage-7.6.10-cp313-cp313t-win_amd64.whl", hash = "sha256:54a5f0f43950a36312155dae55c505a76cd7f2b12d26abeebbe7a0b36dbc868d", size = 212781 }, - { url = "https://files.pythonhosted.org/packages/40/41/473617aadf9a1c15bc2d56be65d90d7c29bfa50a957a67ef96462f7ebf8e/coverage-7.6.10-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:656c82b8a0ead8bba147de9a89bda95064874c91a3ed43a00e687f23cc19d53a", size = 207978 }, - { url = "https://files.pythonhosted.org/packages/10/f6/480586607768b39a30e6910a3c4522139094ac0f1677028e1f4823688957/coverage-7.6.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ccc2b70a7ed475c68ceb548bf69cec1e27305c1c2606a5eb7c3afff56a1b3b27", size = 208415 }, - { url = "https://files.pythonhosted.org/packages/f1/af/439bb760f817deff6f4d38fe7da08d9dd7874a560241f1945bc3b4446550/coverage-7.6.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5e37dc41d57ceba70956fa2fc5b63c26dba863c946ace9705f8eca99daecdc4", size = 236452 }, - { url = "https://files.pythonhosted.org/packages/d0/13/481f4ceffcabe29ee2332e60efb52e4694f54a402f3ada2bcec10bb32e43/coverage-7.6.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0aa9692b4fdd83a4647eeb7db46410ea1322b5ed94cd1715ef09d1d5922ba87f", size = 234374 }, - { url = "https://files.pythonhosted.org/packages/c5/59/4607ea9d6b1b73e905c7656da08d0b00cdf6e59f2293ec259e8914160025/coverage-7.6.10-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa744da1820678b475e4ba3dfd994c321c5b13381d1041fe9c608620e6676e25", size = 235505 }, - { url = "https://files.pythonhosted.org/packages/85/60/d66365723b9b7f29464b11d024248ed3523ce5aab958e4ad8c43f3f4148b/coverage-7.6.10-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c0b1818063dc9e9d838c09e3a473c1422f517889436dd980f5d721899e66f315", size = 234616 }, - { url = "https://files.pythonhosted.org/packages/74/f8/2cf7a38e7d81b266f47dfcf137fecd8fa66c7bdbd4228d611628d8ca3437/coverage-7.6.10-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:59af35558ba08b758aec4d56182b222976330ef8d2feacbb93964f576a7e7a90", size = 233099 }, - { url = "https://files.pythonhosted.org/packages/50/2b/bff6c1c6b63c4396ea7ecdbf8db1788b46046c681b8fcc6ec77db9f4ea49/coverage-7.6.10-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7ed2f37cfce1ce101e6dffdfd1c99e729dd2ffc291d02d3e2d0af8b53d13840d", size = 234089 }, - { url = "https://files.pythonhosted.org/packages/bf/b5/baace1c754d546a67779358341aa8d2f7118baf58cac235db457e1001d1b/coverage-7.6.10-cp39-cp39-win32.whl", hash = "sha256:4bcc276261505d82f0ad426870c3b12cb177752834a633e737ec5ee79bbdff18", size = 210701 }, - { url = "https://files.pythonhosted.org/packages/b1/bf/9e1e95b8b20817398ecc5a1e8d3e05ff404e1b9fb2185cd71561698fe2a2/coverage-7.6.10-cp39-cp39-win_amd64.whl", hash = "sha256:457574f4599d2b00f7f637a0700a6422243b3565509457b2dbd3f50703e11f59", size = 211482 }, - { url = "https://files.pythonhosted.org/packages/a1/70/de81bfec9ed38a64fc44a77c7665e20ca507fc3265597c28b0d989e4082e/coverage-7.6.10-pp39.pp310-none-any.whl", hash = "sha256:fd34e7b3405f0cc7ab03d54a334c17a9e802897580d964bd8c2001f4b9fd488f", size = 200223 }, -] - -[package.optional-dependencies] -toml = [ - { name = "tomli", marker = "python_full_version >= '3.9' and python_full_version <= '3.11'" }, + { name = "tomli", marker = "python_full_version <= '3.11'" }, ] [[package]] @@ -428,7 +325,7 @@ sdist = { url = "https://files.pythonhosted.org/packages/ee/25/4afe0b88b91b49611 [[package]] name = "django-adminactions" -version = "2.3.0" +version = "2.4.dev12+g308f833.d20250210" source = { editable = "." } dependencies = [ { name = "pytz" }, @@ -440,32 +337,26 @@ dependencies = [ dev = [ { name = "celery" }, { name = "check-manifest" }, + { name = "covdefaults" }, { name = "django-admin-extra-urls" }, { name = "django-dynamic-fixture" }, - { name = "django-environ", version = "0.11.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "django-environ", version = "0.12.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "django-environ" }, { name = "django-webtest" }, { name = "mock" }, { name = "modernize" }, - { name = "mypy", version = "1.14.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "mypy", version = "1.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, - { name = "pillow", version = "10.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "pillow", version = "11.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "mypy" }, + { name = "pillow" }, { name = "psycopg2" }, { name = "pytest" }, { name = "pytest-cache" }, - { name = "pytest-cov", version = "5.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "pytest-cov", version = "6.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "pytest-cov" }, { name = "pytest-django" }, - { name = "pytest-echo", version = "1.7.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "pytest-echo", version = "1.8.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "pytest-echo" }, { name = "readme" }, { name = "redis" }, { name = "ruff" }, - { name = "selenium", version = "4.27.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "selenium", version = "4.28.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, - { name = "setuptools", version = "75.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "setuptools", version = "75.8.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "selenium" }, + { name = "setuptools" }, { name = "tox" }, ] @@ -480,6 +371,7 @@ requires-dist = [ dev = [ { name = "celery" }, { name = "check-manifest" }, + { name = "covdefaults", specifier = ">=2.3.0" }, { name = "django-admin-extra-urls" }, { name = "django-dynamic-fixture" }, { name = "django-environ" }, @@ -515,34 +407,17 @@ wheels = [ name = "django-environ" version = "0.11.2" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.9'", -] sdist = { url = "https://files.pythonhosted.org/packages/d6/0b/f2c024529ee4bbf8b95176eebeb86c6e695192a9ce0e91059cb83a33c1d3/django-environ-0.11.2.tar.gz", hash = "sha256:f32a87aa0899894c27d4e1776fa6b477e8164ed7f6b3e410a62a6d72caaf64be", size = 54326 } wheels = [ { url = "https://files.pythonhosted.org/packages/c4/f1/468b49cccba3b42dda571063a14c668bb0b53a1d5712426d18e36663bd53/django_environ-0.11.2-py2.py3-none-any.whl", hash = "sha256:0ff95ab4344bfeff693836aa978e6840abef2e2f1145adff7735892711590c05", size = 19141 }, ] -[[package]] -name = "django-environ" -version = "0.12.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.13'", - "python_full_version >= '3.9' and python_full_version < '3.13'", -] -sdist = { url = "https://files.pythonhosted.org/packages/d6/04/65d2521842c42f4716225f20d8443a50804920606aec018188bbee30a6b0/django_environ-0.12.0.tar.gz", hash = "sha256:227dc891453dd5bde769c3449cf4a74b6f2ee8f7ab2361c93a07068f4179041a", size = 56804 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/83/b3/0a3bec4ecbfee960f39b1842c2f91e4754251e0a6ed443db9fe3f666ba8f/django_environ-0.12.0-py2.py3-none-any.whl", hash = "sha256:92fb346a158abda07ffe6eb23135ce92843af06ecf8753f43adf9d2366dcc0ca", size = 19957 }, -] - [[package]] name = "django-webtest" version = "1.9.12" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "webtest", version = "3.0.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "webtest", version = "3.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "webtest" }, ] sdist = { url = "https://files.pythonhosted.org/packages/47/e3/e087630e62bcf29ed1c3560ae98b12c45e0ac07b4899ab3b8ef6a1967dde/django_webtest-1.9.12.tar.gz", hash = "sha256:5012c30665e7a6e585a1544eda75045d07d5b3f5ccccd4d0fe144c4555884095", size = 28848 } wheels = [ @@ -554,7 +429,7 @@ name = "docutils" version = "0.20.1" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "python_full_version < '3.9'", + "python_full_version < '3.13'", ] sdist = { url = "https://files.pythonhosted.org/packages/1f/53/a5da4f2c5739cf66290fac1431ee52aff6851c7c8ffd8264f13affd7bcdd/docutils-0.20.1.tar.gz", hash = "sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b", size = 2058365 } wheels = [ @@ -567,7 +442,6 @@ version = "0.21.2" source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version >= '3.13'", - "python_full_version >= '3.9' and python_full_version < '3.13'", ] sdist = { url = "https://files.pythonhosted.org/packages/ae/ed/aefcc8cd0ba62a0560c3c18c33925362d46c6075480bfa4df87b28e169a9/docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f", size = 2204444 } wheels = [ @@ -596,27 +470,11 @@ wheels = [ name = "filelock" version = "3.16.1" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.9'", -] sdist = { url = "https://files.pythonhosted.org/packages/9d/db/3ef5bb276dae18d6ec2124224403d1d67bccdbefc17af4cc8f553e341ab1/filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435", size = 18037 } wheels = [ { url = "https://files.pythonhosted.org/packages/b9/f8/feced7779d755758a52d1f6635d990b8d98dc0a29fa568bbe0625f18fdf3/filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0", size = 16163 }, ] -[[package]] -name = "filelock" -version = "3.17.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.13'", - "python_full_version >= '3.9' and python_full_version < '3.13'", -] -sdist = { url = "https://files.pythonhosted.org/packages/dc/9c/0b15fb47b464e1b663b1acd1253a062aa5feecb07d4e597daea542ebd2b5/filelock-3.17.0.tar.gz", hash = "sha256:ee4e77401ef576ebb38cd7f13b9b28893194acc20a8e68e18730ba9c0e54660e", size = 18027 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/89/ec/00d68c4ddfedfe64159999e5f8a98fb8442729a63e2077eb9dcd89623d27/filelock-3.17.0-py3-none-any.whl", hash = "sha256:533dc2f7ba78dc2f0f531fc6c4940addf7b70a481e269a5a3b93be94ffbe8338", size = 16164 }, -] - [[package]] name = "fissix" version = "24.4.24" @@ -651,32 +509,14 @@ wheels = [ name = "importlib-metadata" version = "8.5.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.9'", -] dependencies = [ - { name = "zipp", version = "3.20.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "zipp", marker = "python_full_version < '3.13'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/cd/12/33e59336dca5be0c398a7482335911a33aa0e20776128f038019f1a95f1b/importlib_metadata-8.5.0.tar.gz", hash = "sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7", size = 55304 } wheels = [ { url = "https://files.pythonhosted.org/packages/a0/d9/a1e041c5e7caa9a05c925f4bdbdfb7f006d1f74996af53467bc394c97be7/importlib_metadata-8.5.0-py3-none-any.whl", hash = "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b", size = 26514 }, ] -[[package]] -name = "importlib-metadata" -version = "8.6.1" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.9' and python_full_version < '3.13'", -] -dependencies = [ - { name = "zipp", version = "3.21.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/33/08/c1395a292bb23fd03bdf572a1357c5a733d3eecbab877641ceacab23db6e/importlib_metadata-8.6.1.tar.gz", hash = "sha256:310b41d755445d74569f993ccfc22838295d9fe005425094fad953d7f15c8580", size = 55767 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/79/9d/0fb148dc4d6fa4a7dd1d8378168d9b4cd8d4560a6fbf6f0121c5fc34eb68/importlib_metadata-8.6.1-py3-none-any.whl", hash = "sha256:02a89390c1e15fdfdc0d7c6b25cb3e62650d0494005c97d6f148bf5b9787525e", size = 26971 }, -] - [[package]] name = "iniconfig" version = "2.0.0" @@ -692,9 +532,8 @@ version = "5.4.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "amqp" }, - { name = "backports-zoneinfo", extra = ["tzdata"], marker = "python_full_version < '3.9'" }, { name = "typing-extensions", marker = "python_full_version < '3.10'" }, - { name = "tzdata", marker = "python_full_version >= '3.9'" }, + { name = "tzdata" }, { name = "vine" }, ] sdist = { url = "https://files.pythonhosted.org/packages/38/4d/b93fcb353d279839cc35d0012bee805ed0cf61c07587916bfc35dbfddaf1/kombu-5.4.2.tar.gz", hash = "sha256:eef572dd2fd9fc614b37580e3caeafdd5af46c1eff31e7fba89138cdb406f2cf", size = 442858 } @@ -736,13 +575,10 @@ wheels = [ name = "mypy" version = "1.14.1" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.9'", -] dependencies = [ - { name = "mypy-extensions", marker = "python_full_version < '3.9'" }, - { name = "tomli", marker = "python_full_version < '3.9'" }, - { name = "typing-extensions", marker = "python_full_version < '3.9'" }, + { name = "mypy-extensions" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/b9/eb/2c92d8ea1e684440f54fa49ac5d9a5f19967b7b472a281f419e69a8d228e/mypy-1.14.1.tar.gz", hash = "sha256:7ec88144fe9b510e8475ec2f5f251992690fcf89ccb4500b214b4226abcd32d6", size = 3216051 } wheels = [ @@ -770,12 +606,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/56/9d/4a236b9c57f5d8f08ed346914b3f091a62dd7e19336b2b2a0d85485f82ff/mypy-1.14.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d4b19b03fdf54f3c5b2fa474c56b4c13c9dbfb9a2db4370ede7ec11a2c5927d9", size = 12867660 }, { url = "https://files.pythonhosted.org/packages/40/88/a61a5497e2f68d9027de2bb139c7bb9abaeb1be1584649fa9d807f80a338/mypy-1.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0c911fde686394753fff899c409fd4e16e9b294c24bfd5e1ea4675deae1ac6fd", size = 12969198 }, { url = "https://files.pythonhosted.org/packages/54/da/3d6fc5d92d324701b0c23fb413c853892bfe0e1dbe06c9138037d459756b/mypy-1.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:8b21525cb51671219f5307be85f7e646a153e5acc656e5cebf64bfa076c50107", size = 9885276 }, - { url = "https://files.pythonhosted.org/packages/39/02/1817328c1372be57c16148ce7d2bfcfa4a796bedaed897381b1aad9b267c/mypy-1.14.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7084fb8f1128c76cd9cf68fe5971b37072598e7c31b2f9f95586b65c741a9d31", size = 11143050 }, - { url = "https://files.pythonhosted.org/packages/b9/07/99db9a95ece5e58eee1dd87ca456a7e7b5ced6798fd78182c59c35a7587b/mypy-1.14.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8f845a00b4f420f693f870eaee5f3e2692fa84cc8514496114649cfa8fd5e2c6", size = 10321087 }, - { url = "https://files.pythonhosted.org/packages/9a/eb/85ea6086227b84bce79b3baf7f465b4732e0785830726ce4a51528173b71/mypy-1.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:44bf464499f0e3a2d14d58b54674dee25c031703b2ffc35064bd0df2e0fac319", size = 12066766 }, - { url = "https://files.pythonhosted.org/packages/4b/bb/f01bebf76811475d66359c259eabe40766d2f8ac8b8250d4e224bb6df379/mypy-1.14.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c99f27732c0b7dc847adb21c9d47ce57eb48fa33a17bc6d7d5c5e9f9e7ae5bac", size = 12787111 }, - { url = "https://files.pythonhosted.org/packages/2f/c9/84837ff891edcb6dcc3c27d85ea52aab0c4a34740ff5f0ccc0eb87c56139/mypy-1.14.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:bce23c7377b43602baa0bd22ea3265c49b9ff0b76eb315d6c34721af4cdf1d9b", size = 12974331 }, - { url = "https://files.pythonhosted.org/packages/84/5f/901e18464e6a13f8949b4909535be3fa7f823291b8ab4e4b36cfe57d6769/mypy-1.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:8edc07eeade7ebc771ff9cf6b211b9a7d93687ff892150cb5692e4f4272b0837", size = 9763210 }, { url = "https://files.pythonhosted.org/packages/ca/1f/186d133ae2514633f8558e78cd658070ba686c0e9275c5a5c24a1e1f0d67/mypy-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3888a1816d69f7ab92092f785a462944b3ca16d7c470d564165fe703b0970c35", size = 11200493 }, { url = "https://files.pythonhosted.org/packages/af/fc/4842485d034e38a4646cccd1369f6b1ccd7bc86989c52770d75d719a9941/mypy-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:46c756a444117c43ee984bd055db99e498bc613a70bbbc120272bd13ca579fbc", size = 10357702 }, { url = "https://files.pythonhosted.org/packages/b4/e6/457b83f2d701e23869cfec013a48a12638f75b9d37612a9ddf99072c1051/mypy-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:27fc248022907e72abfd8e22ab1f10e903915ff69961174784a3900a8cba9ad9", size = 12091104 }, @@ -785,54 +615,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a0/b5/32dd67b69a16d088e533962e5044e51004176a9952419de0370cdaead0f8/mypy-1.14.1-py3-none-any.whl", hash = "sha256:b66a60cc4073aeb8ae00057f9c1f64d49e90f918fbcef9a977eb121da8b8f1d1", size = 2752905 }, ] -[[package]] -name = "mypy" -version = "1.15.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.13'", - "python_full_version >= '3.9' and python_full_version < '3.13'", -] -dependencies = [ - { name = "mypy-extensions", marker = "python_full_version >= '3.9'" }, - { name = "tomli", marker = "python_full_version >= '3.9' and python_full_version < '3.11.0'" }, - { name = "typing-extensions", marker = "python_full_version >= '3.9'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/ce/43/d5e49a86afa64bd3839ea0d5b9c7103487007d728e1293f52525d6d5486a/mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43", size = 3239717 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/68/f8/65a7ce8d0e09b6329ad0c8d40330d100ea343bd4dd04c4f8ae26462d0a17/mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13", size = 10738433 }, - { url = "https://files.pythonhosted.org/packages/b4/95/9c0ecb8eacfe048583706249439ff52105b3f552ea9c4024166c03224270/mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559", size = 9861472 }, - { url = "https://files.pythonhosted.org/packages/84/09/9ec95e982e282e20c0d5407bc65031dfd0f0f8ecc66b69538296e06fcbee/mypy-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be68172e9fd9ad8fb876c6389f16d1c1b5f100ffa779f77b1fb2176fcc9ab95b", size = 11611424 }, - { url = "https://files.pythonhosted.org/packages/78/13/f7d14e55865036a1e6a0a69580c240f43bc1f37407fe9235c0d4ef25ffb0/mypy-1.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c7be1e46525adfa0d97681432ee9fcd61a3964c2446795714699a998d193f1a3", size = 12365450 }, - { url = "https://files.pythonhosted.org/packages/48/e1/301a73852d40c241e915ac6d7bcd7fedd47d519246db2d7b86b9d7e7a0cb/mypy-1.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2e2c2e6d3593f6451b18588848e66260ff62ccca522dd231cd4dd59b0160668b", size = 12551765 }, - { url = "https://files.pythonhosted.org/packages/77/ba/c37bc323ae5fe7f3f15a28e06ab012cd0b7552886118943e90b15af31195/mypy-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:6983aae8b2f653e098edb77f893f7b6aca69f6cffb19b2cc7443f23cce5f4828", size = 9274701 }, - { url = "https://files.pythonhosted.org/packages/03/bc/f6339726c627bd7ca1ce0fa56c9ae2d0144604a319e0e339bdadafbbb599/mypy-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2922d42e16d6de288022e5ca321cd0618b238cfc5570e0263e5ba0a77dbef56f", size = 10662338 }, - { url = "https://files.pythonhosted.org/packages/e2/90/8dcf506ca1a09b0d17555cc00cd69aee402c203911410136cd716559efe7/mypy-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ee2d57e01a7c35de00f4634ba1bbf015185b219e4dc5909e281016df43f5ee5", size = 9787540 }, - { url = "https://files.pythonhosted.org/packages/05/05/a10f9479681e5da09ef2f9426f650d7b550d4bafbef683b69aad1ba87457/mypy-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:973500e0774b85d9689715feeffcc980193086551110fd678ebe1f4342fb7c5e", size = 11538051 }, - { url = "https://files.pythonhosted.org/packages/e9/9a/1f7d18b30edd57441a6411fcbc0c6869448d1a4bacbaee60656ac0fc29c8/mypy-1.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a95fb17c13e29d2d5195869262f8125dfdb5c134dc8d9a9d0aecf7525b10c2c", size = 12286751 }, - { url = "https://files.pythonhosted.org/packages/72/af/19ff499b6f1dafcaf56f9881f7a965ac2f474f69f6f618b5175b044299f5/mypy-1.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1905f494bfd7d85a23a88c5d97840888a7bd516545fc5aaedff0267e0bb54e2f", size = 12421783 }, - { url = "https://files.pythonhosted.org/packages/96/39/11b57431a1f686c1aed54bf794870efe0f6aeca11aca281a0bd87a5ad42c/mypy-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:c9817fa23833ff189db061e6d2eff49b2f3b6ed9856b4a0a73046e41932d744f", size = 9265618 }, - { url = "https://files.pythonhosted.org/packages/98/3a/03c74331c5eb8bd025734e04c9840532226775c47a2c39b56a0c8d4f128d/mypy-1.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:aea39e0583d05124836ea645f412e88a5c7d0fd77a6d694b60d9b6b2d9f184fd", size = 10793981 }, - { url = "https://files.pythonhosted.org/packages/f0/1a/41759b18f2cfd568848a37c89030aeb03534411eef981df621d8fad08a1d/mypy-1.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f2147ab812b75e5b5499b01ade1f4a81489a147c01585cda36019102538615f", size = 9749175 }, - { url = "https://files.pythonhosted.org/packages/12/7e/873481abf1ef112c582db832740f4c11b2bfa510e829d6da29b0ab8c3f9c/mypy-1.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce436f4c6d218a070048ed6a44c0bbb10cd2cc5e272b29e7845f6a2f57ee4464", size = 11455675 }, - { url = "https://files.pythonhosted.org/packages/b3/d0/92ae4cde706923a2d3f2d6c39629134063ff64b9dedca9c1388363da072d/mypy-1.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8023ff13985661b50a5928fc7a5ca15f3d1affb41e5f0a9952cb68ef090b31ee", size = 12410020 }, - { url = "https://files.pythonhosted.org/packages/46/8b/df49974b337cce35f828ba6fda228152d6db45fed4c86ba56ffe442434fd/mypy-1.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1124a18bc11a6a62887e3e137f37f53fbae476dc36c185d549d4f837a2a6a14e", size = 12498582 }, - { url = "https://files.pythonhosted.org/packages/13/50/da5203fcf6c53044a0b699939f31075c45ae8a4cadf538a9069b165c1050/mypy-1.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:171a9ca9a40cd1843abeca0e405bc1940cd9b305eaeea2dda769ba096932bb22", size = 9366614 }, - { url = "https://files.pythonhosted.org/packages/6a/9b/fd2e05d6ffff24d912f150b87db9e364fa8282045c875654ce7e32fffa66/mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445", size = 10788592 }, - { url = "https://files.pythonhosted.org/packages/74/37/b246d711c28a03ead1fd906bbc7106659aed7c089d55fe40dd58db812628/mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d", size = 9753611 }, - { url = "https://files.pythonhosted.org/packages/a6/ac/395808a92e10cfdac8003c3de9a2ab6dc7cde6c0d2a4df3df1b815ffd067/mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5", size = 11438443 }, - { url = "https://files.pythonhosted.org/packages/d2/8b/801aa06445d2de3895f59e476f38f3f8d610ef5d6908245f07d002676cbf/mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036", size = 12402541 }, - { url = "https://files.pythonhosted.org/packages/c7/67/5a4268782eb77344cc613a4cf23540928e41f018a9a1ec4c6882baf20ab8/mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357", size = 12494348 }, - { url = "https://files.pythonhosted.org/packages/83/3e/57bb447f7bbbfaabf1712d96f9df142624a386d98fb026a761532526057e/mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf", size = 9373648 }, - { url = "https://files.pythonhosted.org/packages/5a/fa/79cf41a55b682794abe71372151dbbf856e3008f6767057229e6649d294a/mypy-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e601a7fa172c2131bff456bb3ee08a88360760d0d2f8cbd7a75a65497e2df078", size = 10737129 }, - { url = "https://files.pythonhosted.org/packages/d3/33/dd8feb2597d648de29e3da0a8bf4e1afbda472964d2a4a0052203a6f3594/mypy-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:712e962a6357634fef20412699a3655c610110e01cdaa6180acec7fc9f8513ba", size = 9856335 }, - { url = "https://files.pythonhosted.org/packages/e4/b5/74508959c1b06b96674b364ffeb7ae5802646b32929b7701fc6b18447592/mypy-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95579473af29ab73a10bada2f9722856792a36ec5af5399b653aa28360290a5", size = 11611935 }, - { url = "https://files.pythonhosted.org/packages/6c/53/da61b9d9973efcd6507183fdad96606996191657fe79701b2c818714d573/mypy-1.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f8722560a14cde92fdb1e31597760dc35f9f5524cce17836c0d22841830fd5b", size = 12365827 }, - { url = "https://files.pythonhosted.org/packages/c1/72/965bd9ee89540c79a25778cc080c7e6ef40aa1eeac4d52cec7eae6eb5228/mypy-1.15.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1fbb8da62dc352133d7d7ca90ed2fb0e9d42bb1a32724c287d3c76c58cbaa9c2", size = 12541924 }, - { url = "https://files.pythonhosted.org/packages/46/d0/f41645c2eb263e6c77ada7d76f894c580c9ddb20d77f0c24d34273a4dab2/mypy-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:d10d994b41fb3497719bbf866f227b3489048ea4bbbb5015357db306249f7980", size = 9271176 }, - { url = "https://files.pythonhosted.org/packages/09/4e/a7d65c7322c510de2c409ff3828b03354a7c43f5a8ed458a7a131b41c7b9/mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e", size = 2221777 }, -] - [[package]] name = "mypy-extensions" version = "1.0.0" @@ -898,9 +680,6 @@ wheels = [ name = "pillow" version = "10.4.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.9'", -] sdist = { url = "https://files.pythonhosted.org/packages/cd/74/ad3d526f3bf7b6d3f408b73fde271ec69dfac8b81341a318ce825f2b3812/pillow-10.4.0.tar.gz", hash = "sha256:166c1cd4d24309b30d61f79f4a9114b7b2313d7450912277855ff5dfd7cd4a06", size = 46555059 } wheels = [ { url = "https://files.pythonhosted.org/packages/0e/69/a31cccd538ca0b5272be2a38347f8839b97a14be104ea08b0db92f749c74/pillow-10.4.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:4d9667937cfa347525b319ae34375c37b9ee6b525440f3ef48542fcf66f2731e", size = 3509271 }, @@ -947,16 +726,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7b/f9/cfaa5082ca9bc4a6de66ffe1c12c2d90bf09c309a5f52b27759a596900e7/pillow-10.4.0-cp313-cp313-win32.whl", hash = "sha256:551d3fd6e9dc15e4c1eb6fc4ba2b39c0c7933fa113b220057a34f4bb3268a060", size = 2235603 }, { url = "https://files.pythonhosted.org/packages/01/6a/30ff0eef6e0c0e71e55ded56a38d4859bf9d3634a94a88743897b5f96936/pillow-10.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:030abdbe43ee02e0de642aee345efa443740aa4d828bfe8e2eb11922ea6a21ea", size = 2554972 }, { url = "https://files.pythonhosted.org/packages/48/2c/2e0a52890f269435eee38b21c8218e102c621fe8d8df8b9dd06fabf879ba/pillow-10.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:5b001114dd152cfd6b23befeb28d7aee43553e2402c9f159807bf55f33af8a8d", size = 2243375 }, - { url = "https://files.pythonhosted.org/packages/56/70/f40009702a477ce87d8d9faaa4de51d6562b3445d7a314accd06e4ffb01d/pillow-10.4.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:8d4d5063501b6dd4024b8ac2f04962d661222d120381272deea52e3fc52d3736", size = 3509213 }, - { url = "https://files.pythonhosted.org/packages/10/43/105823d233c5e5d31cea13428f4474ded9d961652307800979a59d6a4276/pillow-10.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7c1ee6f42250df403c5f103cbd2768a28fe1a0ea1f0f03fe151c8741e1469c8b", size = 3375883 }, - { url = "https://files.pythonhosted.org/packages/3c/ad/7850c10bac468a20c918f6a5dbba9ecd106ea1cdc5db3c35e33a60570408/pillow-10.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b15e02e9bb4c21e39876698abf233c8c579127986f8207200bc8a8f6bb27acf2", size = 4330810 }, - { url = "https://files.pythonhosted.org/packages/84/4c/69bbed9e436ac22f9ed193a2b64f64d68fcfbc9f4106249dc7ed4889907b/pillow-10.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a8d4bade9952ea9a77d0c3e49cbd8b2890a399422258a77f357b9cc9be8d680", size = 4444341 }, - { url = "https://files.pythonhosted.org/packages/8f/4f/c183c63828a3f37bf09644ce94cbf72d4929b033b109160a5379c2885932/pillow-10.4.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:43efea75eb06b95d1631cb784aa40156177bf9dd5b4b03ff38979e048258bc6b", size = 4356005 }, - { url = "https://files.pythonhosted.org/packages/fb/ad/435fe29865f98a8fbdc64add8875a6e4f8c97749a93577a8919ec6f32c64/pillow-10.4.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:950be4d8ba92aca4b2bb0741285a46bfae3ca699ef913ec8416c1b78eadd64cd", size = 4525201 }, - { url = "https://files.pythonhosted.org/packages/80/74/be8bf8acdfd70e91f905a12ae13cfb2e17c0f1da745c40141e26d0971ff5/pillow-10.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d7480af14364494365e89d6fddc510a13e5a2c3584cb19ef65415ca57252fb84", size = 4460635 }, - { url = "https://files.pythonhosted.org/packages/e4/90/763616e66dc9ad59c9b7fb58f863755e7934ef122e52349f62c7742b82d3/pillow-10.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:73664fe514b34c8f02452ffb73b7a92c6774e39a647087f83d67f010eb9a0cf0", size = 4590283 }, - { url = "https://files.pythonhosted.org/packages/69/66/03002cb5b2c27bb519cba63b9f9aa3709c6f7a5d3b285406c01f03fb77e5/pillow-10.4.0-cp38-cp38-win32.whl", hash = "sha256:e88d5e6ad0d026fba7bdab8c3f225a69f063f116462c49892b0149e21b6c0a0e", size = 2235185 }, - { url = "https://files.pythonhosted.org/packages/f2/75/3cb820b2812405fc7feb3d0deb701ef0c3de93dc02597115e00704591bc9/pillow-10.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:5161eef006d335e46895297f642341111945e2c1c899eb406882a6c61a4357ab", size = 2554594 }, { url = "https://files.pythonhosted.org/packages/31/85/955fa5400fa8039921f630372cfe5056eed6e1b8e0430ee4507d7de48832/pillow-10.4.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:0ae24a547e8b711ccaaf99c9ae3cd975470e1a30caa80a6aaee9a2f19c05701d", size = 3509283 }, { url = "https://files.pythonhosted.org/packages/23/9c/343827267eb28d41cd82b4180d33b10d868af9077abcec0af9793aa77d2d/pillow-10.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:298478fe4f77a4408895605f3482b6cc6222c018b2ce565c2b6b9c354ac3229b", size = 3375691 }, { url = "https://files.pythonhosted.org/packages/60/a3/7ebbeabcd341eab722896d1a5b59a3df98c4b4d26cf4b0385f8aa94296f7/pillow-10.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:134ace6dc392116566980ee7436477d844520a26a4b1bd4053f6f47d096997fd", size = 4328295 }, @@ -984,88 +753,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/37/ae/2dbfc38cc4fd14aceea14bc440d5151b21f64c4c3ba3f6f4191610b7ee5d/pillow-10.4.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:cfdd747216947628af7b259d274771d84db2268ca062dd5faf373639d00113a3", size = 2554652 }, ] -[[package]] -name = "pillow" -version = "11.1.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.13'", - "python_full_version >= '3.9' and python_full_version < '3.13'", -] -sdist = { url = "https://files.pythonhosted.org/packages/f3/af/c097e544e7bd278333db77933e535098c259609c4eb3b85381109602fb5b/pillow-11.1.0.tar.gz", hash = "sha256:368da70808b36d73b4b390a8ffac11069f8a5c85f29eff1f1b01bcf3ef5b2a20", size = 46742715 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/50/1c/2dcea34ac3d7bc96a1fd1bd0a6e06a57c67167fec2cff8d95d88229a8817/pillow-11.1.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:e1abe69aca89514737465752b4bcaf8016de61b3be1397a8fc260ba33321b3a8", size = 3229983 }, - { url = "https://files.pythonhosted.org/packages/14/ca/6bec3df25e4c88432681de94a3531cc738bd85dea6c7aa6ab6f81ad8bd11/pillow-11.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c640e5a06869c75994624551f45e5506e4256562ead981cce820d5ab39ae2192", size = 3101831 }, - { url = "https://files.pythonhosted.org/packages/d4/2c/668e18e5521e46eb9667b09e501d8e07049eb5bfe39d56be0724a43117e6/pillow-11.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a07dba04c5e22824816b2615ad7a7484432d7f540e6fa86af60d2de57b0fcee2", size = 4314074 }, - { url = "https://files.pythonhosted.org/packages/02/80/79f99b714f0fc25f6a8499ecfd1f810df12aec170ea1e32a4f75746051ce/pillow-11.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e267b0ed063341f3e60acd25c05200df4193e15a4a5807075cd71225a2386e26", size = 4394933 }, - { url = "https://files.pythonhosted.org/packages/81/aa/8d4ad25dc11fd10a2001d5b8a80fdc0e564ac33b293bdfe04ed387e0fd95/pillow-11.1.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:bd165131fd51697e22421d0e467997ad31621b74bfc0b75956608cb2906dda07", size = 4353349 }, - { url = "https://files.pythonhosted.org/packages/84/7a/cd0c3eaf4a28cb2a74bdd19129f7726277a7f30c4f8424cd27a62987d864/pillow-11.1.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:abc56501c3fd148d60659aae0af6ddc149660469082859fa7b066a298bde9482", size = 4476532 }, - { url = "https://files.pythonhosted.org/packages/8f/8b/a907fdd3ae8f01c7670dfb1499c53c28e217c338b47a813af8d815e7ce97/pillow-11.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:54ce1c9a16a9561b6d6d8cb30089ab1e5eb66918cb47d457bd996ef34182922e", size = 4279789 }, - { url = "https://files.pythonhosted.org/packages/6f/9a/9f139d9e8cccd661c3efbf6898967a9a337eb2e9be2b454ba0a09533100d/pillow-11.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:73ddde795ee9b06257dac5ad42fcb07f3b9b813f8c1f7f870f402f4dc54b5269", size = 4413131 }, - { url = "https://files.pythonhosted.org/packages/a8/68/0d8d461f42a3f37432203c8e6df94da10ac8081b6d35af1c203bf3111088/pillow-11.1.0-cp310-cp310-win32.whl", hash = "sha256:3a5fe20a7b66e8135d7fd617b13272626a28278d0e578c98720d9ba4b2439d49", size = 2291213 }, - { url = "https://files.pythonhosted.org/packages/14/81/d0dff759a74ba87715509af9f6cb21fa21d93b02b3316ed43bda83664db9/pillow-11.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:b6123aa4a59d75f06e9dd3dac5bf8bc9aa383121bb3dd9a7a612e05eabc9961a", size = 2625725 }, - { url = "https://files.pythonhosted.org/packages/ce/1f/8d50c096a1d58ef0584ddc37e6f602828515219e9d2428e14ce50f5ecad1/pillow-11.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:a76da0a31da6fcae4210aa94fd779c65c75786bc9af06289cd1c184451ef7a65", size = 2375213 }, - { url = "https://files.pythonhosted.org/packages/dd/d6/2000bfd8d5414fb70cbbe52c8332f2283ff30ed66a9cde42716c8ecbe22c/pillow-11.1.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:e06695e0326d05b06833b40b7ef477e475d0b1ba3a6d27da1bb48c23209bf457", size = 3229968 }, - { url = "https://files.pythonhosted.org/packages/d9/45/3fe487010dd9ce0a06adf9b8ff4f273cc0a44536e234b0fad3532a42c15b/pillow-11.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96f82000e12f23e4f29346e42702b6ed9a2f2fea34a740dd5ffffcc8c539eb35", size = 3101806 }, - { url = "https://files.pythonhosted.org/packages/e3/72/776b3629c47d9d5f1c160113158a7a7ad177688d3a1159cd3b62ded5a33a/pillow-11.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3cd561ded2cf2bbae44d4605837221b987c216cff94f49dfeed63488bb228d2", size = 4322283 }, - { url = "https://files.pythonhosted.org/packages/e4/c2/e25199e7e4e71d64eeb869f5b72c7ddec70e0a87926398785ab944d92375/pillow-11.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f189805c8be5ca5add39e6f899e6ce2ed824e65fb45f3c28cb2841911da19070", size = 4402945 }, - { url = "https://files.pythonhosted.org/packages/c1/ed/51d6136c9d5911f78632b1b86c45241c712c5a80ed7fa7f9120a5dff1eba/pillow-11.1.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:dd0052e9db3474df30433f83a71b9b23bd9e4ef1de13d92df21a52c0303b8ab6", size = 4361228 }, - { url = "https://files.pythonhosted.org/packages/48/a4/fbfe9d5581d7b111b28f1d8c2762dee92e9821bb209af9fa83c940e507a0/pillow-11.1.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:837060a8599b8f5d402e97197d4924f05a2e0d68756998345c829c33186217b1", size = 4484021 }, - { url = "https://files.pythonhosted.org/packages/39/db/0b3c1a5018117f3c1d4df671fb8e47d08937f27519e8614bbe86153b65a5/pillow-11.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:aa8dd43daa836b9a8128dbe7d923423e5ad86f50a7a14dc688194b7be5c0dea2", size = 4287449 }, - { url = "https://files.pythonhosted.org/packages/d9/58/bc128da7fea8c89fc85e09f773c4901e95b5936000e6f303222490c052f3/pillow-11.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0a2f91f8a8b367e7a57c6e91cd25af510168091fb89ec5146003e424e1558a96", size = 4419972 }, - { url = "https://files.pythonhosted.org/packages/5f/bb/58f34379bde9fe197f51841c5bbe8830c28bbb6d3801f16a83b8f2ad37df/pillow-11.1.0-cp311-cp311-win32.whl", hash = "sha256:c12fc111ef090845de2bb15009372175d76ac99969bdf31e2ce9b42e4b8cd88f", size = 2291201 }, - { url = "https://files.pythonhosted.org/packages/3a/c6/fce9255272bcf0c39e15abd2f8fd8429a954cf344469eaceb9d0d1366913/pillow-11.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:fbd43429d0d7ed6533b25fc993861b8fd512c42d04514a0dd6337fb3ccf22761", size = 2625686 }, - { url = "https://files.pythonhosted.org/packages/c8/52/8ba066d569d932365509054859f74f2a9abee273edcef5cd75e4bc3e831e/pillow-11.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:f7955ecf5609dee9442cbface754f2c6e541d9e6eda87fad7f7a989b0bdb9d71", size = 2375194 }, - { url = "https://files.pythonhosted.org/packages/95/20/9ce6ed62c91c073fcaa23d216e68289e19d95fb8188b9fb7a63d36771db8/pillow-11.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2062ffb1d36544d42fcaa277b069c88b01bb7298f4efa06731a7fd6cc290b81a", size = 3226818 }, - { url = "https://files.pythonhosted.org/packages/b9/d8/f6004d98579a2596c098d1e30d10b248798cceff82d2b77aa914875bfea1/pillow-11.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a85b653980faad27e88b141348707ceeef8a1186f75ecc600c395dcac19f385b", size = 3101662 }, - { url = "https://files.pythonhosted.org/packages/08/d9/892e705f90051c7a2574d9f24579c9e100c828700d78a63239676f960b74/pillow-11.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9409c080586d1f683df3f184f20e36fb647f2e0bc3988094d4fd8c9f4eb1b3b3", size = 4329317 }, - { url = "https://files.pythonhosted.org/packages/8c/aa/7f29711f26680eab0bcd3ecdd6d23ed6bce180d82e3f6380fb7ae35fcf3b/pillow-11.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7fdadc077553621911f27ce206ffcbec7d3f8d7b50e0da39f10997e8e2bb7f6a", size = 4412999 }, - { url = "https://files.pythonhosted.org/packages/c8/c4/8f0fe3b9e0f7196f6d0bbb151f9fba323d72a41da068610c4c960b16632a/pillow-11.1.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:93a18841d09bcdd774dcdc308e4537e1f867b3dec059c131fde0327899734aa1", size = 4368819 }, - { url = "https://files.pythonhosted.org/packages/38/0d/84200ed6a871ce386ddc82904bfadc0c6b28b0c0ec78176871a4679e40b3/pillow-11.1.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:9aa9aeddeed452b2f616ff5507459e7bab436916ccb10961c4a382cd3e03f47f", size = 4496081 }, - { url = "https://files.pythonhosted.org/packages/84/9c/9bcd66f714d7e25b64118e3952d52841a4babc6d97b6d28e2261c52045d4/pillow-11.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3cdcdb0b896e981678eee140d882b70092dac83ac1cdf6b3a60e2216a73f2b91", size = 4296513 }, - { url = "https://files.pythonhosted.org/packages/db/61/ada2a226e22da011b45f7104c95ebda1b63dcbb0c378ad0f7c2a710f8fd2/pillow-11.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:36ba10b9cb413e7c7dfa3e189aba252deee0602c86c309799da5a74009ac7a1c", size = 4431298 }, - { url = "https://files.pythonhosted.org/packages/e7/c4/fc6e86750523f367923522014b821c11ebc5ad402e659d8c9d09b3c9d70c/pillow-11.1.0-cp312-cp312-win32.whl", hash = "sha256:cfd5cd998c2e36a862d0e27b2df63237e67273f2fc78f47445b14e73a810e7e6", size = 2291630 }, - { url = "https://files.pythonhosted.org/packages/08/5c/2104299949b9d504baf3f4d35f73dbd14ef31bbd1ddc2c1b66a5b7dfda44/pillow-11.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:a697cd8ba0383bba3d2d3ada02b34ed268cb548b369943cd349007730c92bddf", size = 2626369 }, - { url = "https://files.pythonhosted.org/packages/37/f3/9b18362206b244167c958984b57c7f70a0289bfb59a530dd8af5f699b910/pillow-11.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:4dd43a78897793f60766563969442020e90eb7847463eca901e41ba186a7d4a5", size = 2375240 }, - { url = "https://files.pythonhosted.org/packages/b3/31/9ca79cafdce364fd5c980cd3416c20ce1bebd235b470d262f9d24d810184/pillow-11.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ae98e14432d458fc3de11a77ccb3ae65ddce70f730e7c76140653048c71bfcbc", size = 3226640 }, - { url = "https://files.pythonhosted.org/packages/ac/0f/ff07ad45a1f172a497aa393b13a9d81a32e1477ef0e869d030e3c1532521/pillow-11.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cc1331b6d5a6e144aeb5e626f4375f5b7ae9934ba620c0ac6b3e43d5e683a0f0", size = 3101437 }, - { url = "https://files.pythonhosted.org/packages/08/2f/9906fca87a68d29ec4530be1f893149e0cb64a86d1f9f70a7cfcdfe8ae44/pillow-11.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:758e9d4ef15d3560214cddbc97b8ef3ef86ce04d62ddac17ad39ba87e89bd3b1", size = 4326605 }, - { url = "https://files.pythonhosted.org/packages/b0/0f/f3547ee15b145bc5c8b336401b2d4c9d9da67da9dcb572d7c0d4103d2c69/pillow-11.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b523466b1a31d0dcef7c5be1f20b942919b62fd6e9a9be199d035509cbefc0ec", size = 4411173 }, - { url = "https://files.pythonhosted.org/packages/b1/df/bf8176aa5db515c5de584c5e00df9bab0713548fd780c82a86cba2c2fedb/pillow-11.1.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:9044b5e4f7083f209c4e35aa5dd54b1dd5b112b108648f5c902ad586d4f945c5", size = 4369145 }, - { url = "https://files.pythonhosted.org/packages/de/7c/7433122d1cfadc740f577cb55526fdc39129a648ac65ce64db2eb7209277/pillow-11.1.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:3764d53e09cdedd91bee65c2527815d315c6b90d7b8b79759cc48d7bf5d4f114", size = 4496340 }, - { url = "https://files.pythonhosted.org/packages/25/46/dd94b93ca6bd555588835f2504bd90c00d5438fe131cf01cfa0c5131a19d/pillow-11.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:31eba6bbdd27dde97b0174ddf0297d7a9c3a507a8a1480e1e60ef914fe23d352", size = 4296906 }, - { url = "https://files.pythonhosted.org/packages/a8/28/2f9d32014dfc7753e586db9add35b8a41b7a3b46540e965cb6d6bc607bd2/pillow-11.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b5d658fbd9f0d6eea113aea286b21d3cd4d3fd978157cbf2447a6035916506d3", size = 4431759 }, - { url = "https://files.pythonhosted.org/packages/33/48/19c2cbe7403870fbe8b7737d19eb013f46299cdfe4501573367f6396c775/pillow-11.1.0-cp313-cp313-win32.whl", hash = "sha256:f86d3a7a9af5d826744fabf4afd15b9dfef44fe69a98541f666f66fbb8d3fef9", size = 2291657 }, - { url = "https://files.pythonhosted.org/packages/3b/ad/285c556747d34c399f332ba7c1a595ba245796ef3e22eae190f5364bb62b/pillow-11.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:593c5fd6be85da83656b93ffcccc2312d2d149d251e98588b14fbc288fd8909c", size = 2626304 }, - { url = "https://files.pythonhosted.org/packages/e5/7b/ef35a71163bf36db06e9c8729608f78dedf032fc8313d19bd4be5c2588f3/pillow-11.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:11633d58b6ee5733bde153a8dafd25e505ea3d32e261accd388827ee987baf65", size = 2375117 }, - { url = "https://files.pythonhosted.org/packages/79/30/77f54228401e84d6791354888549b45824ab0ffde659bafa67956303a09f/pillow-11.1.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:70ca5ef3b3b1c4a0812b5c63c57c23b63e53bc38e758b37a951e5bc466449861", size = 3230060 }, - { url = "https://files.pythonhosted.org/packages/ce/b1/56723b74b07dd64c1010fee011951ea9c35a43d8020acd03111f14298225/pillow-11.1.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:8000376f139d4d38d6851eb149b321a52bb8893a88dae8ee7d95840431977081", size = 3106192 }, - { url = "https://files.pythonhosted.org/packages/e1/cd/7bf7180e08f80a4dcc6b4c3a0aa9e0b0ae57168562726a05dc8aa8fa66b0/pillow-11.1.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ee85f0696a17dd28fbcfceb59f9510aa71934b483d1f5601d1030c3c8304f3c", size = 4446805 }, - { url = "https://files.pythonhosted.org/packages/97/42/87c856ea30c8ed97e8efbe672b58c8304dee0573f8c7cab62ae9e31db6ae/pillow-11.1.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:dd0e081319328928531df7a0e63621caf67652c8464303fd102141b785ef9547", size = 4530623 }, - { url = "https://files.pythonhosted.org/packages/ff/41/026879e90c84a88e33fb00cc6bd915ac2743c67e87a18f80270dfe3c2041/pillow-11.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e63e4e5081de46517099dc30abe418122f54531a6ae2ebc8680bcd7096860eab", size = 4465191 }, - { url = "https://files.pythonhosted.org/packages/e5/fb/a7960e838bc5df57a2ce23183bfd2290d97c33028b96bde332a9057834d3/pillow-11.1.0-cp313-cp313t-win32.whl", hash = "sha256:dda60aa465b861324e65a78c9f5cf0f4bc713e4309f83bc387be158b077963d9", size = 2295494 }, - { url = "https://files.pythonhosted.org/packages/d7/6c/6ec83ee2f6f0fda8d4cf89045c6be4b0373ebfc363ba8538f8c999f63fcd/pillow-11.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ad5db5781c774ab9a9b2c4302bbf0c1014960a0a7be63278d13ae6fdf88126fe", size = 2631595 }, - { url = "https://files.pythonhosted.org/packages/cf/6c/41c21c6c8af92b9fea313aa47c75de49e2f9a467964ee33eb0135d47eb64/pillow-11.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:67cd427c68926108778a9005f2a04adbd5e67c442ed21d95389fe1d595458756", size = 2377651 }, - { url = "https://files.pythonhosted.org/packages/9a/1f/9df5ac77491fddd2e36c352d16976dc11fbe6ab842f5df85fd7e31b847b9/pillow-11.1.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:bf902d7413c82a1bfa08b06a070876132a5ae6b2388e2712aab3a7cbc02205c6", size = 3229995 }, - { url = "https://files.pythonhosted.org/packages/a6/62/c7b359e924dca274173b04922ac06aa63614f7e934d132f2fe1d852509aa/pillow-11.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c1eec9d950b6fe688edee07138993e54ee4ae634c51443cfb7c1e7613322718e", size = 3101890 }, - { url = "https://files.pythonhosted.org/packages/7b/63/136f21340a434de895b62bcf2c386005a8aa24066c4facd619f5e0e9f283/pillow-11.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e275ee4cb11c262bd108ab2081f750db2a1c0b8c12c1897f27b160c8bd57bbc", size = 4310366 }, - { url = "https://files.pythonhosted.org/packages/f6/46/0bd0ca03d9d1164a7fa33d285ef6d1c438e963d0c8770e4c5b3737ef5abe/pillow-11.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4db853948ce4e718f2fc775b75c37ba2efb6aaea41a1a5fc57f0af59eee774b2", size = 4391582 }, - { url = "https://files.pythonhosted.org/packages/0c/55/f182db572b28bd833b8e806f933f782ceb2df64c40e4d8bd3d4226a46eca/pillow-11.1.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:ab8a209b8485d3db694fa97a896d96dd6533d63c22829043fd9de627060beade", size = 4350278 }, - { url = "https://files.pythonhosted.org/packages/75/fb/e330fdbbcbc4744214b5f53b84d9d8a9f4ffbebc2e9c2ac10475386e3296/pillow-11.1.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:54251ef02a2309b5eec99d151ebf5c9904b77976c8abdcbce7891ed22df53884", size = 4471768 }, - { url = "https://files.pythonhosted.org/packages/eb/51/20ee6c4da4448d7a67ffb720a5fcdb965115a78e211a1f58f9845ae15f86/pillow-11.1.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5bb94705aea800051a743aa4874bb1397d4695fb0583ba5e425ee0328757f196", size = 4276549 }, - { url = "https://files.pythonhosted.org/packages/37/f2/a25c0bdaa6d6fd5cc3d4a6f65b5a7ea46e7af58bee00a98efe0a5af79c58/pillow-11.1.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:89dbdb3e6e9594d512780a5a1c42801879628b38e3efc7038094430844e271d8", size = 4409350 }, - { url = "https://files.pythonhosted.org/packages/12/a7/06687947604cd3e47abeea1b78b65d34ffce7feab03cfe0dd985f115dca3/pillow-11.1.0-cp39-cp39-win32.whl", hash = "sha256:e5449ca63da169a2e6068dd0e2fcc8d91f9558aba89ff6d02121ca8ab11e79e5", size = 2291271 }, - { url = "https://files.pythonhosted.org/packages/21/a6/f51d47675940b5c63b08ff0575b3518428b4acb891f88526fa4ee1edab6f/pillow-11.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:3362c6ca227e65c54bf71a5f88b3d4565ff1bcbc63ae72c34b07bbb1cc59a43f", size = 2625783 }, - { url = "https://files.pythonhosted.org/packages/95/56/97750bd33e68648fa432dfadcb8ede7624bd905822d42262d34bcebdd9d7/pillow-11.1.0-cp39-cp39-win_arm64.whl", hash = "sha256:b20be51b37a75cc54c2c55def3fa2c65bb94ba859dde241cd0a4fd302de5ae0a", size = 2375193 }, - { url = "https://files.pythonhosted.org/packages/fa/c5/389961578fb677b8b3244fcd934f720ed25a148b9a5cc81c91bdf59d8588/pillow-11.1.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:8c730dc3a83e5ac137fbc92dfcfe1511ce3b2b5d7578315b63dbbb76f7f51d90", size = 3198345 }, - { url = "https://files.pythonhosted.org/packages/c4/fa/803c0e50ffee74d4b965229e816af55276eac1d5806712de86f9371858fd/pillow-11.1.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:7d33d2fae0e8b170b6a6c57400e077412240f6f5bb2a342cf1ee512a787942bb", size = 3072938 }, - { url = "https://files.pythonhosted.org/packages/dc/67/2a3a5f8012b5d8c63fe53958ba906c1b1d0482ebed5618057ef4d22f8076/pillow-11.1.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a8d65b38173085f24bc07f8b6c505cbb7418009fa1a1fcb111b1f4961814a442", size = 3400049 }, - { url = "https://files.pythonhosted.org/packages/e5/a0/514f0d317446c98c478d1872497eb92e7cde67003fed74f696441e647446/pillow-11.1.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:015c6e863faa4779251436db398ae75051469f7c903b043a48f078e437656f83", size = 3422431 }, - { url = "https://files.pythonhosted.org/packages/cd/00/20f40a935514037b7d3f87adfc87d2c538430ea625b63b3af8c3f5578e72/pillow-11.1.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d44ff19eea13ae4acdaaab0179fa68c0c6f2f45d66a4d8ec1eda7d6cecbcc15f", size = 3446208 }, - { url = "https://files.pythonhosted.org/packages/28/3c/7de681727963043e093c72e6c3348411b0185eab3263100d4490234ba2f6/pillow-11.1.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:d3d8da4a631471dfaf94c10c85f5277b1f8e42ac42bade1ac67da4b4a7359b73", size = 3509746 }, - { url = "https://files.pythonhosted.org/packages/41/67/936f9814bdd74b2dfd4822f1f7725ab5d8ff4103919a1664eb4874c58b2f/pillow-11.1.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:4637b88343166249fe8aa94e7c4a62a180c4b3898283bb5d3d2fd5fe10d8e4e0", size = 2626353 }, -] - [[package]] name = "platformdirs" version = "4.3.6" @@ -1135,35 +822,15 @@ wheels = [ name = "pyproject-api" version = "1.8.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.9'", -] dependencies = [ - { name = "packaging", marker = "python_full_version < '3.9'" }, - { name = "tomli", marker = "python_full_version < '3.9'" }, + { name = "packaging" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/bb/19/441e0624a8afedd15bbcce96df1b80479dd0ff0d965f5ce8fde4f2f6ffad/pyproject_api-1.8.0.tar.gz", hash = "sha256:77b8049f2feb5d33eefcc21b57f1e279636277a8ac8ad6b5871037b243778496", size = 22340 } wheels = [ { url = "https://files.pythonhosted.org/packages/ba/f4/3c4ddfcc0c19c217c6de513842d286de8021af2f2ab79bbb86c00342d778/pyproject_api-1.8.0-py3-none-any.whl", hash = "sha256:3d7d347a047afe796fd5d1885b1e391ba29be7169bd2f102fcd378f04273d228", size = 13100 }, ] -[[package]] -name = "pyproject-api" -version = "1.9.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.13'", - "python_full_version >= '3.9' and python_full_version < '3.13'", -] -dependencies = [ - { name = "packaging", marker = "python_full_version >= '3.9'" }, - { name = "tomli", marker = "python_full_version >= '3.9' and python_full_version < '3.11.0'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/7e/66/fdc17e94486836eda4ba7113c0db9ac7e2f4eea1b968ee09de2fe75e391b/pyproject_api-1.9.0.tar.gz", hash = "sha256:7e8a9854b2dfb49454fae421cb86af43efbb2b2454e5646ffb7623540321ae6e", size = 22714 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b0/1d/92b7c765df46f454889d9610292b0ccab15362be3119b9a624458455e8d5/pyproject_api-1.9.0-py3-none-any.whl", hash = "sha256:326df9d68dea22d9d98b5243c46e3ca3161b07a1b9b18e213d1e24fd0e605766", size = 13131 }, -] - [[package]] name = "pyproject-hooks" version = "1.2.0" @@ -1188,11 +855,11 @@ version = "8.3.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, - { name = "exceptiongroup", marker = "python_full_version < '3.11.0'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, { name = "iniconfig" }, { name = "packaging" }, { name = "pluggy" }, - { name = "tomli", marker = "python_full_version < '3.11.0'" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/05/35/30e0d83068951d90a01852cb1cef56e5d8a09d20c7f511634cc2f7e0372a/pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761", size = 1445919 } wheels = [ @@ -1213,35 +880,15 @@ sdist = { url = "https://files.pythonhosted.org/packages/d1/15/082fd0428aab33d2b name = "pytest-cov" version = "5.0.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.9'", -] dependencies = [ - { name = "coverage", version = "7.6.1", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version < '3.9'" }, - { name = "pytest", marker = "python_full_version < '3.9'" }, + { name = "coverage", extra = ["toml"] }, + { name = "pytest" }, ] sdist = { url = "https://files.pythonhosted.org/packages/74/67/00efc8d11b630c56f15f4ad9c7f9223f1e5ec275aaae3fa9118c6a223ad2/pytest-cov-5.0.0.tar.gz", hash = "sha256:5837b58e9f6ebd335b0f8060eecce69b662415b16dc503883a02f45dfeb14857", size = 63042 } wheels = [ { url = "https://files.pythonhosted.org/packages/78/3a/af5b4fa5961d9a1e6237b530eb87dd04aea6eb83da09d2a4073d81b54ccf/pytest_cov-5.0.0-py3-none-any.whl", hash = "sha256:4f0764a1219df53214206bf1feea4633c3b558a2925c8b59f144f682861ce652", size = 21990 }, ] -[[package]] -name = "pytest-cov" -version = "6.0.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.13'", - "python_full_version >= '3.9' and python_full_version < '3.13'", -] -dependencies = [ - { name = "coverage", version = "7.6.10", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version >= '3.9'" }, - { name = "pytest", marker = "python_full_version >= '3.9'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/be/45/9b538de8cef30e17c7b45ef42f538a94889ed6a16f2387a6c89e73220651/pytest-cov-6.0.0.tar.gz", hash = "sha256:fde0b595ca248bb8e2d76f020b465f3b107c9632e6a1d1705f17834c89dcadc0", size = 66945 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/36/3b/48e79f2cd6a61dbbd4807b4ed46cb564b4fd50a76166b1c4ea5c1d9e2371/pytest_cov-6.0.0-py3-none-any.whl", hash = "sha256:eee6f1b9e61008bd34975a4d5bab25801eb31898b032dd55addc93e96fcaaa35", size = 22949 }, -] - [[package]] name = "pytest-django" version = "4.9.0" @@ -1258,33 +905,14 @@ wheels = [ name = "pytest-echo" version = "1.7.3" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.9'", -] dependencies = [ - { name = "pytest", marker = "python_full_version < '3.9'" }, + { name = "pytest" }, ] sdist = { url = "https://files.pythonhosted.org/packages/37/0e/a5dcb4a634dcbdba8a97d1201c8c8a95405e6f504e055e1e9a10e4b939d3/pytest-echo-1.7.3.tar.gz", hash = "sha256:2307af560ebbdc77967579e577f24015467fbcf80cabb9b04d225348bb8d9474", size = 13948 } wheels = [ { url = "https://files.pythonhosted.org/packages/af/d2/155f0ffc8d5c1091c9b5aaec93325c4729b2474e00729f1ac320310268cc/pytest_echo-1.7.3-py2.py3-none-any.whl", hash = "sha256:683f4d2fef8dd701aeaf47db834ccc114d43f580abcfea53f3ce2ffe8166c3c0", size = 5744 }, ] -[[package]] -name = "pytest-echo" -version = "1.8.1" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.13'", - "python_full_version >= '3.9' and python_full_version < '3.13'", -] -dependencies = [ - { name = "pytest", marker = "python_full_version >= '3.9'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/4d/48/fc27028f166c25623ac0c1d401bce3a77662050edadb06d87bec1da2c63f/pytest_echo-1.8.1.tar.gz", hash = "sha256:7d765b4ddac93468fa1d303e70c48ad9e38479b4d122d5ae019919bb7fed0c2a", size = 14863 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b0/c6/50ae25410db72d9051329ca9337ffe90e9155858a64fcd1e7ce76b9168c6/pytest_echo-1.8.1-py2.py3-none-any.whl", hash = "sha256:2bc47fa7faf30fcbd39651667d69f199603599941cf3d6c5d296586799a19bfd", size = 5798 }, -] - [[package]] name = "python-dateutil" version = "2.9.0.post0" @@ -1311,8 +939,7 @@ name = "readme" version = "0.7.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "readme-renderer", version = "43.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "readme-renderer", version = "44.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "readme-renderer" }, ] sdist = { url = "https://files.pythonhosted.org/packages/e2/b5/831f3f29e64107a4222d7156a45f81bfdc6f0f29af9af96f3fe173a5d060/readme-0.7.1.tar.gz", hash = "sha256:32fbe1538a437da160fa4e4477270bfdcd8876e2e364d0d12898302644496231", size = 5914 } wheels = [ @@ -1323,37 +950,17 @@ wheels = [ name = "readme-renderer" version = "43.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.9'", -] dependencies = [ - { name = "docutils", version = "0.20.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "nh3", marker = "python_full_version < '3.9'" }, - { name = "pygments", marker = "python_full_version < '3.9'" }, + { name = "docutils", version = "0.20.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.13'" }, + { name = "docutils", version = "0.21.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.13'" }, + { name = "nh3" }, + { name = "pygments" }, ] sdist = { url = "https://files.pythonhosted.org/packages/fe/b5/536c775084d239df6345dccf9b043419c7e3308bc31be4c7882196abc62e/readme_renderer-43.0.tar.gz", hash = "sha256:1818dd28140813509eeed8d62687f7cd4f7bad90d4db586001c5dc09d4fde311", size = 31768 } wheels = [ { url = "https://files.pythonhosted.org/packages/45/be/3ea20dc38b9db08387cf97997a85a7d51527ea2057d71118feb0aa8afa55/readme_renderer-43.0-py3-none-any.whl", hash = "sha256:19db308d86ecd60e5affa3b2a98f017af384678c63c88e5d4556a380e674f3f9", size = 13301 }, ] -[[package]] -name = "readme-renderer" -version = "44.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.13'", - "python_full_version >= '3.9' and python_full_version < '3.13'", -] -dependencies = [ - { name = "docutils", version = "0.21.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, - { name = "nh3", marker = "python_full_version >= '3.9'" }, - { name = "pygments", marker = "python_full_version >= '3.9'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/5a/a9/104ec9234c8448c4379768221ea6df01260cd6c2ce13182d4eac531c8342/readme_renderer-44.0.tar.gz", hash = "sha256:8712034eabbfa6805cacf1402b4eeb2a73028f72d1166d6f5cb7f9c047c5d1e1", size = 32056 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e1/67/921ec3024056483db83953ae8e48079ad62b92db7880013ca77632921dd0/readme_renderer-44.0-py3-none-any.whl", hash = "sha256:2fbca89b81a08526aadf1357a8c2ae889ec05fb03f5da67f9769c9a592166151", size = 13310 }, -] - [[package]] name = "redis" version = "5.2.1" @@ -1395,68 +1002,28 @@ wheels = [ name = "selenium" version = "4.27.1" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.9'", -] dependencies = [ - { name = "certifi", marker = "python_full_version < '3.9'" }, - { name = "trio", version = "0.27.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "trio-websocket", marker = "python_full_version < '3.9'" }, - { name = "typing-extensions", marker = "python_full_version < '3.9'" }, - { name = "urllib3", version = "2.2.3", source = { registry = "https://pypi.org/simple" }, extra = ["socks"], marker = "python_full_version < '3.9'" }, - { name = "websocket-client", marker = "python_full_version < '3.9'" }, + { name = "certifi" }, + { name = "trio" }, + { name = "trio-websocket" }, + { name = "typing-extensions" }, + { name = "urllib3", extra = ["socks"] }, + { name = "websocket-client" }, ] sdist = { url = "https://files.pythonhosted.org/packages/44/8c/62c47c91072aa03af1c3b7d7f1c59b987db41c9fec0f158fb03a0da51aa6/selenium-4.27.1.tar.gz", hash = "sha256:5296c425a75ff1b44d0d5199042b36a6d1ef76c04fb775b97b40be739a9caae2", size = 973526 } wheels = [ { url = "https://files.pythonhosted.org/packages/a6/1e/5f1a5dd2a28528c4b3ec6e076b58e4c035810c805328f9936123283ca14e/selenium-4.27.1-py3-none-any.whl", hash = "sha256:b89b1f62b5cfe8025868556fe82360d6b649d464f75d2655cb966c8f8447ea18", size = 9707007 }, ] -[[package]] -name = "selenium" -version = "4.28.1" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.13'", - "python_full_version >= '3.9' and python_full_version < '3.13'", -] -dependencies = [ - { name = "certifi", marker = "python_full_version >= '3.9'" }, - { name = "trio", version = "0.28.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, - { name = "trio-websocket", marker = "python_full_version >= '3.9'" }, - { name = "typing-extensions", marker = "python_full_version >= '3.9'" }, - { name = "urllib3", version = "2.3.0", source = { registry = "https://pypi.org/simple" }, extra = ["socks"], marker = "python_full_version >= '3.9'" }, - { name = "websocket-client", marker = "python_full_version >= '3.9'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/88/38/d62d4e8da649ad699b02eb1e95c3cfc20ff400744b9417b9093c5daebd4b/selenium-4.28.1.tar.gz", hash = "sha256:0072d08670d7ec32db901bd0107695a330cecac9f196e3afb3fa8163026e022a", size = 981633 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a0/9f/34d0ec09b0dd6fb7b08b93eb4b7b80049e0b9db0ba7f81ad814c9be78b8f/selenium-4.28.1-py3-none-any.whl", hash = "sha256:4238847e45e24e4472cfcf3554427512c7aab9443396435b1623ef406fff1cc1", size = 9530373 }, -] - [[package]] name = "setuptools" version = "75.3.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.9'", -] sdist = { url = "https://files.pythonhosted.org/packages/ed/22/a438e0caa4576f8c383fa4d35f1cc01655a46c75be358960d815bfbb12bd/setuptools-75.3.0.tar.gz", hash = "sha256:fba5dd4d766e97be1b1681d98712680ae8f2f26d7881245f2ce9e40714f1a686", size = 1351577 } wheels = [ { url = "https://files.pythonhosted.org/packages/90/12/282ee9bce8b58130cb762fbc9beabd531549952cac11fc56add11dcb7ea0/setuptools-75.3.0-py3-none-any.whl", hash = "sha256:f2504966861356aa38616760c0f66568e535562374995367b4e69c7143cf6bcd", size = 1251070 }, ] -[[package]] -name = "setuptools" -version = "75.8.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.13'", - "python_full_version >= '3.9' and python_full_version < '3.13'", -] -sdist = { url = "https://files.pythonhosted.org/packages/92/ec/089608b791d210aec4e7f97488e67ab0d33add3efccb83a056cbafe3a2a6/setuptools-75.8.0.tar.gz", hash = "sha256:c5afc8f407c626b8313a86e10311dd3f661c6cd9c09d4bf8c15c0e11f9f2b0e6", size = 1343222 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/69/8a/b9dc7678803429e4a3bc9ba462fa3dd9066824d3c607490235c6a796be5a/setuptools-75.8.0-py3-none-any.whl", hash = "sha256:e3982f444617239225d675215d51f6ba05f845d4eec313da4418fdbb56fb27e3", size = 1228782 }, -] - [[package]] name = "six" version = "1.17.0" @@ -1540,15 +1107,13 @@ dependencies = [ { name = "cachetools" }, { name = "chardet" }, { name = "colorama" }, - { name = "filelock", version = "3.16.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "filelock", version = "3.17.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "filelock" }, { name = "packaging" }, { name = "platformdirs" }, { name = "pluggy" }, - { name = "pyproject-api", version = "1.8.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "pyproject-api", version = "1.9.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, - { name = "tomli", marker = "python_full_version < '3.11.0'" }, - { name = "typing-extensions", marker = "python_full_version < '3.11.0'" }, + { name = "pyproject-api" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, { name = "virtualenv" }, ] sdist = { url = "https://files.pythonhosted.org/packages/cf/7b/97f757e159983737bdd8fb513f4c263cd411a846684814ed5433434a1fa9/tox-4.24.1.tar.gz", hash = "sha256:083a720adbc6166fff0b7d1df9d154f9d00bfccb9403b8abf6bc0ee435d6a62e", size = 194742 } @@ -1560,53 +1125,27 @@ wheels = [ name = "trio" version = "0.27.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.9'", -] dependencies = [ - { name = "attrs", marker = "python_full_version < '3.9'" }, - { name = "cffi", marker = "python_full_version < '3.9' and implementation_name != 'pypy' and os_name == 'nt'" }, - { name = "exceptiongroup", marker = "python_full_version < '3.9'" }, - { name = "idna", marker = "python_full_version < '3.9'" }, - { name = "outcome", marker = "python_full_version < '3.9'" }, - { name = "sniffio", marker = "python_full_version < '3.9'" }, - { name = "sortedcontainers", marker = "python_full_version < '3.9'" }, + { name = "attrs" }, + { name = "cffi", marker = "implementation_name != 'pypy' and os_name == 'nt'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "idna" }, + { name = "outcome" }, + { name = "sniffio" }, + { name = "sortedcontainers" }, ] sdist = { url = "https://files.pythonhosted.org/packages/17/d1/a83dee5be404da7afe5a71783a33b8907bacb935a6dc8c69ab785e4a3eed/trio-0.27.0.tar.gz", hash = "sha256:1dcc95ab1726b2da054afea8fd761af74bad79bd52381b84eae408e983c76831", size = 568064 } wheels = [ { url = "https://files.pythonhosted.org/packages/3c/83/ec3196c360afffbc5b342ead48d1eb7393dd74fa70bca75d33905a86f211/trio-0.27.0-py3-none-any.whl", hash = "sha256:68eabbcf8f457d925df62da780eff15ff5dc68fd6b367e2dde59f7aaf2a0b884", size = 481734 }, ] -[[package]] -name = "trio" -version = "0.28.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.13'", - "python_full_version >= '3.9' and python_full_version < '3.13'", -] -dependencies = [ - { name = "attrs", marker = "python_full_version >= '3.9'" }, - { name = "cffi", marker = "python_full_version >= '3.9' and implementation_name != 'pypy' and os_name == 'nt'" }, - { name = "exceptiongroup", marker = "python_full_version >= '3.9' and python_full_version < '3.11.0'" }, - { name = "idna", marker = "python_full_version >= '3.9'" }, - { name = "outcome", marker = "python_full_version >= '3.9'" }, - { name = "sniffio", marker = "python_full_version >= '3.9'" }, - { name = "sortedcontainers", marker = "python_full_version >= '3.9'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/b3/73/57efab729506a8d4b89814f1e356ec8f3369de0ed4fd7e7616974d09646d/trio-0.28.0.tar.gz", hash = "sha256:4e547896fe9e8a5658e54e4c7c5fa1db748cbbbaa7c965e7d40505b928c73c05", size = 580318 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b4/04/9954a59e1fb6732f5436225c9af963811d7b24ea62a8bf96991f2cb8c26e/trio-0.28.0-py3-none-any.whl", hash = "sha256:56d58977acc1635735a96581ec70513cc781b8b6decd299c487d3be2a721cd94", size = 486317 }, -] - [[package]] name = "trio-websocket" version = "0.11.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "exceptiongroup", marker = "python_full_version < '3.11.0'" }, - { name = "trio", version = "0.27.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "trio", version = "0.28.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "trio" }, { name = "wsproto" }, ] sdist = { url = "https://files.pythonhosted.org/packages/dd/36/abad2385853077424a11b818d9fd8350d249d9e31d583cb9c11cd4c85eda/trio-websocket-0.11.1.tar.gz", hash = "sha256:18c11793647703c158b1f6e62de638acada927344d534e3c7628eedcb746839f", size = 26511 } @@ -1636,9 +1175,6 @@ wheels = [ name = "urllib3" version = "2.2.3" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.9'", -] sdist = { url = "https://files.pythonhosted.org/packages/ed/63/22ba4ebfe7430b76388e7cd448d5478814d3032121827c12a2cc287e2260/urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9", size = 300677 } wheels = [ { url = "https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac", size = 126338 }, @@ -1646,25 +1182,7 @@ wheels = [ [package.optional-dependencies] socks = [ - { name = "pysocks", marker = "python_full_version < '3.9'" }, -] - -[[package]] -name = "urllib3" -version = "2.3.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.13'", - "python_full_version >= '3.9' and python_full_version < '3.13'", -] -sdist = { url = "https://files.pythonhosted.org/packages/aa/63/e53da845320b757bf29ef6a9062f5c669fe997973f966045cb019c3f4b66/urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d", size = 307268 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c8/19/4ec628951a74043532ca2cf5d97b7b14863931476d117c471e8e2b1eb39f/urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df", size = 128369 }, -] - -[package.optional-dependencies] -socks = [ - { name = "pysocks", marker = "python_full_version >= '3.9'" }, + { name = "pysocks" }, ] [[package]] @@ -1682,8 +1200,7 @@ version = "20.29.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "distlib" }, - { name = "filelock", version = "3.16.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "filelock", version = "3.17.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "filelock" }, { name = "platformdirs" }, ] sdist = { url = "https://files.pythonhosted.org/packages/a7/ca/f23dcb02e161a9bba141b1c08aa50e8da6ea25e6d780528f1d385a3efe25/virtualenv-20.29.1.tar.gz", hash = "sha256:b8b8970138d32fb606192cb97f6cd4bb644fa486be9308fb9b63f81091b5dc35", size = 7658028 } @@ -1695,27 +1212,11 @@ wheels = [ name = "waitress" version = "3.0.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.9'", -] sdist = { url = "https://files.pythonhosted.org/packages/70/34/cb77e5249c433eb177a11ab7425056b32d3b57855377fa1e38b397412859/waitress-3.0.0.tar.gz", hash = "sha256:005da479b04134cdd9dd602d1ee7c49d79de0537610d653674cc6cbde222b8a1", size = 179393 } wheels = [ { url = "https://files.pythonhosted.org/packages/5b/a9/485c953a1ac4cb98c28e41fd2c7184072df36bbf99734a51d44d04176878/waitress-3.0.0-py3-none-any.whl", hash = "sha256:2a06f242f4ba0cc563444ca3d1998959447477363a2d7e9b8b4d75d35cfd1669", size = 56698 }, ] -[[package]] -name = "waitress" -version = "3.0.2" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.13'", - "python_full_version >= '3.9' and python_full_version < '3.13'", -] -sdist = { url = "https://files.pythonhosted.org/packages/bf/cb/04ddb054f45faa306a230769e868c28b8065ea196891f09004ebace5b184/waitress-3.0.2.tar.gz", hash = "sha256:682aaaf2af0c44ada4abfb70ded36393f0e307f4ab9456a215ce0020baefc31f", size = 179901 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/8d/57/a27182528c90ef38d82b636a11f606b0cbb0e17588ed205435f8affe3368/waitress-3.0.2-py3-none-any.whl", hash = "sha256:c56d67fd6e87c2ee598b76abdd4e96cfad1f24cacdea5078d382b1f9d7b5ed2e", size = 56232 }, -] - [[package]] name = "wcwidth" version = "0.2.13" @@ -1750,37 +1251,16 @@ wheels = [ name = "webtest" version = "3.0.1" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.9'", -] dependencies = [ - { name = "beautifulsoup4", marker = "python_full_version < '3.9'" }, - { name = "waitress", version = "3.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "webob", marker = "python_full_version < '3.9'" }, + { name = "beautifulsoup4" }, + { name = "waitress" }, + { name = "webob" }, ] sdist = { url = "https://files.pythonhosted.org/packages/20/7e/7534c43c97234d0b5c9f228bb9646c4611e0fa33c2cefeb2e968be96d27e/webtest-3.0.1.tar.gz", hash = "sha256:493b5c802f8948a65b5e3a1ad5b2524ee5e1ab60cd713d9a3da3b8da082c06fe", size = 79278 } wheels = [ { url = "https://files.pythonhosted.org/packages/2b/6d/075023456a2ff8e01ef07afa069563f0d1e1a2fd359d7dbd7672a5bf218a/WebTest-3.0.1-py3-none-any.whl", hash = "sha256:b3bc75d020d0576ee93a5f149666045e58fe2400ea5f0c214d7430d7d213d0d0", size = 32154 }, ] -[[package]] -name = "webtest" -version = "3.0.4" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.13'", - "python_full_version >= '3.9' and python_full_version < '3.13'", -] -dependencies = [ - { name = "beautifulsoup4", marker = "python_full_version >= '3.9'" }, - { name = "waitress", version = "3.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, - { name = "webob", marker = "python_full_version >= '3.9'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/26/c5/b25980d591b111f3898c27b140bc30977794157522a8da91f5bbb5de99b7/webtest-3.0.4.tar.gz", hash = "sha256:94778d19a37e5abd7388dad4d93874410ecced53a1739a8e5ff2dbcba1cfc0c4", size = 79395 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/bc/69/df392f611d46b1ca32e829ba7db1a01d147875cfd51942c39c3f9dc1e48d/WebTest-3.0.4-py3-none-any.whl", hash = "sha256:5b3d8c69ac9057f17750ed5b45320a411423c2b4196bec6450961be98b03d8c1", size = 32149 }, -] - [[package]] name = "wsproto" version = "1.2.0" @@ -1815,22 +1295,7 @@ wheels = [ name = "zipp" version = "3.20.2" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.9'", -] sdist = { url = "https://files.pythonhosted.org/packages/54/bf/5c0000c44ebc80123ecbdddba1f5dcd94a5ada602a9c225d84b5aaa55e86/zipp-3.20.2.tar.gz", hash = "sha256:bc9eb26f4506fda01b81bcde0ca78103b6e62f991b381fec825435c836edbc29", size = 24199 } wheels = [ { url = "https://files.pythonhosted.org/packages/62/8b/5ba542fa83c90e09eac972fc9baca7a88e7e7ca4b221a89251954019308b/zipp-3.20.2-py3-none-any.whl", hash = "sha256:a817ac80d6cf4b23bf7f2828b7cabf326f15a001bea8b1f9b49631780ba28350", size = 9200 }, ] - -[[package]] -name = "zipp" -version = "3.21.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.9' and python_full_version < '3.13'", -] -sdist = { url = "https://files.pythonhosted.org/packages/3f/50/bad581df71744867e9468ebd0bcd6505de3b275e06f202c2cb016e3ff56f/zipp-3.21.0.tar.gz", hash = "sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4", size = 24545 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/1a/7e4798e9339adc931158c9d69ecc34f5e6791489d469f5e50ec15e35f458/zipp-3.21.0-py3-none-any.whl", hash = "sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931", size = 9630 }, -] From d1dc3649be665e4baaed851cf2816fe5eb6bdaee Mon Sep 17 00:00:00 2001 From: Stefano Apostolico Date: Mon, 10 Feb 2025 20:47:49 +0100 Subject: [PATCH 11/14] updates CI --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7088340a..ffb056f1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -32,8 +32,8 @@ jobs: strategy: fail-fast: false matrix: - python-version: [ "3.10", "3.11", "3.12" ] - django-version: [ "3.2", "4.2", "5.0" ] + python-version: [ "310", "311", "312", "3.13" ] + django-version: [ "32", "42", "5.1" ] env: PY_VER: ${{ matrix.python-version}} DJ_VER: ${{ matrix.django-version}} From 985fe54e83e908aeaf6c8a8ca08fb4c793a72e03 Mon Sep 17 00:00:00 2001 From: Stefano Apostolico Date: Mon, 10 Feb 2025 20:49:27 +0100 Subject: [PATCH 12/14] updates CI --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ffb056f1..9d9d449a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -32,8 +32,8 @@ jobs: strategy: fail-fast: false matrix: - python-version: [ "310", "311", "312", "3.13" ] - django-version: [ "32", "42", "5.1" ] + python-version: [ "311", "312", "313" ] + django-version: [ "32", "42", "51" ] env: PY_VER: ${{ matrix.python-version}} DJ_VER: ${{ matrix.django-version}} From 44250fe7ad179278c59ed6fa7dc07a5604bd96d5 Mon Sep 17 00:00:00 2001 From: Stefano Apostolico Date: Mon, 10 Feb 2025 20:54:55 +0100 Subject: [PATCH 13/14] updates pyproject.toml --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index ce3d0f1c..34aeb973 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,7 +22,7 @@ classifiers = [ "Framework :: Django", "Framework :: Django :: 3.2", "Framework :: Django :: 4.2", - "Framework :: Django :: 5.0", + "Framework :: Django :: 5.1", "Intended Audience :: Developers", "Operating System :: OS Independent", "Programming Language :: Python :: 3 :: Only", From 260646c9aa6028b10393b1417f034edc0cc6a662 Mon Sep 17 00:00:00 2001 From: Stefano Apostolico Date: Tue, 11 Feb 2025 11:17:40 +0100 Subject: [PATCH 14/14] add ability to asynchronously mass_update M2M --- CHANGES | 6 +- MANIFEST.in | 22 +-- pyproject.toml | 14 ++ src/adminactions/graph.py | 10 +- src/adminactions/mass_update.py | 30 +++- src/adminactions/requirements/develop.pip | 6 - src/adminactions/requirements/install.py2.pip | 0 src/adminactions/requirements/install.py3.pip | 0 tests/demo/migrations/0001_initial.py | 137 ------------------ tests/demo/models.py | 2 + tests/test_graph.py | 64 +++++++- tests/test_mass_update.py | 19 ++- tox.ini | 1 + 13 files changed, 132 insertions(+), 179 deletions(-) delete mode 100644 src/adminactions/requirements/develop.pip delete mode 100644 src/adminactions/requirements/install.py2.pip delete mode 100644 src/adminactions/requirements/install.py3.pip delete mode 100644 tests/demo/migrations/0001_initial.py diff --git a/CHANGES b/CHANGES index f91205e2..270bd1d1 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,8 @@ -Release 2.4 (dev) -================= +Release 2.4 +=========== * fixes #227 +* add ability to asynchronously mass_update M2M + Release 2.3 =========== diff --git a/MANIFEST.in b/MANIFEST.in index 23b1afbf..2905cc8a 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,25 +1,27 @@ +graft docs +include CHANGELOG +include LICENSE +include src/*.py +include README.md + include README.md include MANIFEST.in include AUTHORS.rst include CHANGES include LICENSE -include tox.ini include *.py exclude .editorconfig exclude manage.py exclude .* +exclude .act +exclude * -recursive-include docs * -recursive-include src *.css -recursive-include src *.js -recursive-include src *.pip -recursive-include src *.po -recursive-include src *.txt -recursive-include src/adminactions *.py -recursive-include src/adminactions *.html -recursive-include tests * +recursive-include src/adminactions *.* +recursive-exclude .act * global-exclude *.pyc global-exclude __pycache__ +global-exclude ~* global-exclude *~ +global-exclude .* diff --git a/pyproject.toml b/pyproject.toml index 34aeb973..c96a75a0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -77,6 +77,20 @@ dev = [ build.hooks.vcs.version-file = "src/adminactions/version.py" version.source = "vcs" +[tool.hatch.build.targets.sdist] +ignore-vcs = true +include = [ + "src/adminactions/**/*.*", +] +exclude = [ + ".gitignore", +] +packages = [ "src/adminactions" ] + +[tool.hatch.build.targets.wheel] +packages = [ "src/adminactions" ] +only-packages = true + [tool.ruff] target-version = "py311" line-length = 120 diff --git a/src/adminactions/graph.py b/src/adminactions/graph.py index e558b529..77c64ae9 100644 --- a/src/adminactions/graph.py +++ b/src/adminactions/graph.py @@ -129,7 +129,7 @@ def graph_queryset(modeladmin: "ModelAdmin", request: "HttpRequest", queryset: " json.dumps(data_labels), json.dumps(data_labels), ) - elif graph_type == "PieChart": + else: # graph_type == "PieChart": table = [list(zip(list(map(str, data_labels)), list(map(str, data))))] extra = """{seriesDefaults: {renderer: jQuery.jqplot.PieRenderer, rendererOptions: {fill: true, @@ -149,13 +149,7 @@ def graph_queryset(modeladmin: "ModelAdmin", request: "HttpRequest", queryset: " modeladmin=modeladmin, form=form, ) - elif request.method == "POST": - initial = { - helpers.ACTION_CHECKBOX_NAME: request.POST.getlist(helpers.ACTION_CHECKBOX_NAME), - "select_across": request.POST.get("select_across", 0), - } - form = MForm(initial=initial) - else: + else: # if request.method == "POST": initial = { helpers.ACTION_CHECKBOX_NAME: request.POST.getlist(helpers.ACTION_CHECKBOX_NAME), "select_across": request.POST.get("select_across", 0), diff --git a/src/adminactions/mass_update.py b/src/adminactions/mass_update.py index d3ac78e5..e296200c 100644 --- a/src/adminactions/mass_update.py +++ b/src/adminactions/mass_update.py @@ -14,6 +14,7 @@ from django.core.files import File from django.db.models import FileField, ForeignKey from django.db.models import fields as df +from django.db.models.query import QuerySet from django.db.transaction import atomic from django.forms import fields as ff from django.forms.models import ( @@ -38,7 +39,6 @@ from .utils import curry, get_field_by_name if TYPE_CHECKING: - from django.db.models.query import QuerySet from django.http.request import HttpRequest @@ -208,10 +208,17 @@ def _post_clean(self) -> None: def full_clean(self) -> None: super().full_clean() + + def _is_field_name(n: str) -> bool: + return not (n.startswith(("chk_id_", "func_id_"))) + + def _is_enabled(n: str) -> bool: + return self.cleaned_data[f"chk_id_{n}"] + if not self.is_bound: # Stop further processing. return for field_name, value in list(self.cleaned_data.items()): - if isinstance(self.fields.get(field_name, ""), forms.FileField): + if _is_field_name(field_name) and isinstance(self.fields.get(field_name, ""), forms.FileField): if self.cleaned_data["_async"] and self.cleaned_data.get(field_name, None): self.add_error(field_name, _("Cannot use Async with FileField")) @@ -220,7 +227,11 @@ def full_clean(self) -> None: self.add_error(None, "Cannot use operators without 'validate'") else: for field_name, value in list(self.cleaned_data.items()): - if isinstance(self.fields.get(field_name, ""), ModelMultipleChoiceField): + if ( + _is_field_name(field_name) + and _is_enabled(field_name) + and isinstance(self.fields.get(field_name, ""), ModelMultipleChoiceField) + ): self.add_error( field_name, _("Unable no mass update ManyToManyField without 'validate'"), @@ -233,13 +244,13 @@ def _clean_fields(self) -> None: try: value = raw_value initial = self.initial.get(name, field.initial) + enabler = "chk_id_%s" % name + apply = self.data.get(enabler, "") == "on" + self.cleaned_data[enabler] = apply if isinstance(field, ff.FileField): value = field.clean(raw_value, initial) else: - enabler = "chk_id_%s" % name function = self.data.get("func_id_%s" % name, "") - apply = self.data.get(enabler, "") == "on" - self.cleaned_data[enabler] = apply self.cleaned_data["func_id_%s" % name] = function # self.cleaned_data[name] = field.clean(raw_value) if apply: @@ -254,7 +265,7 @@ def _clean_fields(self) -> None: value = curry(func, value) else: value = func - self.cleaned_data[name] = value + # self.cleaned_data[name] = value if hasattr(self, "clean_%s" % name): value = getattr(self, "clean_%s" % name)() self.cleaned_data[name] = value @@ -454,7 +465,10 @@ def _get_sample() -> dict[str, list[tuple[Any, str] | dict[str, Any]]]: op = form.data.get("func_id_%s" % field_name) if callable(value): value = None - rules[field_name] = (op, value) + if isinstance(value, QuerySet): + rules[field_name] = (op, list(value.values_list("pk", flat=True))) + else: + rules[field_name] = (op, value) if use_celery: from .tasks import mass_update_task diff --git a/src/adminactions/requirements/develop.pip b/src/adminactions/requirements/develop.pip deleted file mode 100644 index d0e52ea6..00000000 --- a/src/adminactions/requirements/develop.pip +++ /dev/null @@ -1,6 +0,0 @@ -autopep8 -ipython -isort -pdbpp -virtualenv==12.0.2 # do not upgrade. unable to create py3 -wheel diff --git a/src/adminactions/requirements/install.py2.pip b/src/adminactions/requirements/install.py2.pip deleted file mode 100644 index e69de29b..00000000 diff --git a/src/adminactions/requirements/install.py3.pip b/src/adminactions/requirements/install.py3.pip deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/demo/migrations/0001_initial.py b/tests/demo/migrations/0001_initial.py deleted file mode 100644 index b95e1131..00000000 --- a/tests/demo/migrations/0001_initial.py +++ /dev/null @@ -1,137 +0,0 @@ -# Generated by Django 5.1.6 on 2025-02-07 08:31 - -import uuid - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - -import demo.models - - -class Migration(migrations.Migration): - initial = True - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ] - - operations = [ - migrations.CreateModel( - name="DemoModel", - fields=[ - ( - "id", - models.BigAutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("char", models.CharField(max_length=255, verbose_name="Chäř")), - ("integer", models.IntegerField()), - ("logic", models.BooleanField(default=False)), - ("date", models.DateField()), - ("datetime", models.DateTimeField()), - ("time", models.TimeField()), - ("decimal", models.DecimalField(decimal_places=3, max_digits=10)), - ("email", models.EmailField(max_length=254)), - ("float", models.FloatField()), - ("bigint", models.BigIntegerField()), - ("generic_ip", models.GenericIPAddressField()), - ("url", models.URLField()), - ("text", models.TextField()), - ( - "uuid", - models.UUIDField(default=uuid.uuid4, editable=False, unique=True), - ), - ("unique", models.CharField(max_length=255, unique=True)), - ("nullable", models.CharField(max_length=255, null=True)), - ("blank", models.CharField(blank=True, max_length=255, null=True)), - ( - "not_editable", - models.CharField(blank=True, editable=False, max_length=255, null=True), - ), - ( - "choices", - models.IntegerField(choices=[(1, "Choice 1"), (2, "Choice 2"), (3, "Choice 3")]), - ), - ("image", models.ImageField(blank=True, null=True, upload_to="")), - ( - "subclassed_image", - demo.models.SubclassedImageField(blank=True, null=True, upload_to=""), - ), - ], - options={ - "ordering": ("-id",), - }, - ), - migrations.CreateModel( - name="DemoOneToOne", - fields=[ - ( - "id", - models.BigAutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ( - "demo", - models.OneToOneField( - on_delete=django.db.models.deletion.CASCADE, - related_name="onetoone", - to="demo.demomodel", - ), - ), - ], - ), - migrations.CreateModel( - name="DemoRelated", - fields=[ - ( - "id", - models.BigAutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ( - "demo", - models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, - related_name="related", - to="demo.demomodel", - to_field="uuid", - ), - ), - ], - ), - migrations.CreateModel( - name="UserDetail", - fields=[ - ( - "id", - models.BigAutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("note", models.CharField(blank=True, max_length=10)), - ( - "user", - models.ForeignKey( - on_delete=django.db.models.deletion.CASCADE, - to=settings.AUTH_USER_MODEL, - ), - ), - ], - ), - ] diff --git a/tests/demo/models.py b/tests/demo/models.py index 9a888603..55085b1c 100644 --- a/tests/demo/models.py +++ b/tests/demo/models.py @@ -44,6 +44,8 @@ class DemoModel(models.Model): image = models.ImageField(blank=True, null=True) subclassed_image = SubclassedImageField(blank=True, null=True) + m2m = models.ManyToManyField("self", blank=True) + class Meta: app_label = "demo" ordering = ("-id",) diff --git a/tests/test_graph.py b/tests/test_graph.py index 9e0c7bec..eee109f7 100644 --- a/tests/test_graph.py +++ b/tests/test_graph.py @@ -1,6 +1,9 @@ from __future__ import annotations +from pathlib import Path + from django.contrib.auth.models import User +from django.core.management import call_command from django.urls import reverse from django_dynamic_fixture import G from django_webtest import WebTest @@ -35,7 +38,7 @@ def _run_action(self, steps=2): return res - def test_graph_apply(self) -> None: + def test_piegraph_configure(self) -> None: url = reverse("admin:auth_user_changelist") res = self.app.get(url, user="sax") form = res.forms["changelist-form"] @@ -45,9 +48,9 @@ def test_graph_apply(self) -> None: res = form.submit() res.forms["charts-form"]["graph_type"] = "PieChart" res.forms["charts-form"]["axes_x"] = "is_staff" - res = res.forms["charts-form"].submit("apply") + res = res.forms["charts-form"].submit() - def test_graph_post(self) -> None: + def test_piegraph_apply(self) -> None: url = reverse("admin:auth_user_changelist") res = self.app.get(url, user="sax") form = res.forms["changelist-form"] @@ -57,4 +60,59 @@ def test_graph_post(self) -> None: res = form.submit() res.forms["charts-form"]["graph_type"] = "PieChart" res.forms["charts-form"]["axes_x"] = "is_staff" + res = res.forms["charts-form"].submit("apply") + + def test_bargraph_configure(self) -> None: + url = reverse("admin:auth_user_changelist") + res = self.app.get(url, user="sax") + form = res.forms["changelist-form"] + form["action"] = "graph_queryset" + for i in range(11): + form.set("_selected_action", True, i) + res = form.submit() + res.forms["charts-form"]["graph_type"] = "BarChart" + res.forms["charts-form"]["axes_x"] = "is_staff" res = res.forms["charts-form"].submit() + + def test_bargraph_apply(self) -> None: + url = reverse("admin:auth_user_changelist") + res = self.app.get(url, user="sax") + form = res.forms["changelist-form"] + form["action"] = "graph_queryset" + for i in range(11): + form.set("_selected_action", True, i) + res = form.submit() + res.forms["charts-form"]["graph_type"] = "BarChart" + res.forms["charts-form"]["axes_x"] = "is_staff" + res = res.forms["charts-form"].submit("apply") + + def test_bargraph_invalid(self) -> None: + url = reverse("admin:auth_user_changelist") + res = self.app.get(url, user="sax") + form = res.forms["changelist-form"] + form["action"] = "graph_queryset" + for i in range(11): + form.set("_selected_action", True, i) + res = form.submit() + res.forms["charts-form"]["graph_type"] = "BarChart" + # res.forms["charts-form"]["axes_x"] = "is_staff" + res = res.forms["charts-form"].submit("apply") + assert res.status_code == 200 + + +# +# +# def test_graph_foreignkey(django_db_setup, django_db_blocker, app, admin_user: User) -> None: +# with django_db_blocker.unblock(): +# call_command("loaddata", str(Path(__file__).parent / "demo" / "fixtures" / "demoproject.json")) +# url = reverse("admin:demo_demomodel_changelist") +# res = app.get(url, user=admin_user) +# form = res.forms["changelist-form"] +# form["action"] = "graph_queryset" +# for i in range(3): +# form.set("_selected_action", True, i) +# res = form.submit() +# res.forms["charts-form"]["graph_type"] = "PieChart" +# res.forms["charts-form"]["axes_x"] = "logic" +# res = res.forms["charts-form"].submit("apply") +# res.showbrowser() diff --git a/tests/test_mass_update.py b/tests/test_mass_update.py index 80ac1dcd..0287d74f 100644 --- a/tests/test_mass_update.py +++ b/tests/test_mass_update.py @@ -1,4 +1,3 @@ -# from adminactions.signals import adminaction_requested, adminaction_start, adminaction_end from __future__ import annotations from pathlib import Path @@ -74,7 +73,7 @@ def _run_action(self, steps=2, **kwargs): selected_rows = kwargs.pop("selected_rows", self._selected_rows) with user_grant_permission( self.user, - ["demo.change_demomodel", "demo.adminactions_massupdate_demomodel"], + ["demo.change_demomodel", "demo.adminactions_massupdate_demomodel", "demo.view_demomodel",], ): res = self.app.get("/", user="user") res = res.click("Demo models") @@ -108,7 +107,7 @@ def test_custom_modeladmin_form(self) -> None: DemoModelAdmin.mass_update_form = DemoModelMassUpdateForm with user_grant_permission( self.user, - ["demo.change_demomodel", "demo.adminactions_massupdate_demomodel"], + ["demo.change_demomodel", "demo.adminactions_massupdate_demomodel", "demo.view_demomodel",], ): res = self.app.get("/", user="user") res = res.click("Demo models") @@ -174,7 +173,7 @@ def test_async_qs(self) -> None: # Create handler res = self._run_action(_async=1, _validate=0, chk_id_char=False) - assert res.status_code == 302 + assert res.status_code == 302, res.showbrowser() assert DemoModel.objects.filter(choices=1).exists() @patch("adminactions.mass_update.adminaction_end.send") @@ -183,7 +182,7 @@ def test_async_qs(self) -> None: @skipIf(not celery_present, "Celery not installed") def test_async_single(self, req, start, end) -> None: res = self._run_action(_async=1, _validate=1) - assert res.status_code == 302 + assert res.status_code == 302, res.showbrowser() assert req.called assert start.called assert end.called @@ -198,8 +197,18 @@ def test_file_field(self) -> None: obj2 = DemoModel.objects.get(pk=2) assert obj1.image.read() == obj2.image.read() + def test_file_field_prevent_async(self) -> None: res = self._run_action( _async=1, select_across=1, chk_id_image=True, image=Upload(str(Path(__file__).parent / "test.jpeg")) ) assert res.status_code == 200 + + + def test_m2m_sync(self) -> None: + self._run_action(_async=0, select_across=1, chk_id_m2m=True, m2m=[1]) + assert DemoModel.objects.filter(m2m__id=1).exists() + + def test_m2m_async(self) -> None: + self._run_action(_async=1, select_across=1, chk_id_m2m=True, m2m=[1]) + assert DemoModel.objects.filter(m2m__id=1).exists() diff --git a/tox.ini b/tox.ini index cf89d46e..80f76f30 100644 --- a/tox.ini +++ b/tox.ini @@ -12,6 +12,7 @@ description = run the tests with pytest package = wheel wheel_build_env = .pkg deps = + celery d32: django==3.2.* d42: django==4.2.* d51: django==5.1.*