diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml
deleted file mode 100644
index 3e3e1df..0000000
--- a/.github/dependabot.yaml
+++ /dev/null
@@ -1,7 +0,0 @@
-version: 2
-updates:
-
- - package-ecosystem: github-actions
- directory: /
- schedule:
- interval: monthly
diff --git a/.github/release.yaml b/.github/release.yaml
deleted file mode 100644
index ee081a1..0000000
--- a/.github/release.yaml
+++ /dev/null
@@ -1,18 +0,0 @@
-changelog:
- exclude:
- labels:
- - ignore-for-release
- authors:
- - dependabot
- categories:
- - title: Breaking Changes π
- labels:
- - semver-major
- - breaking-change
- - title: New Features π
- labels:
- - semver-minor
- - enhancement
- - title: Other Changes
- labels:
- - '*'
\ No newline at end of file
diff --git a/.github/workflows/bench.yaml b/.github/workflows/bench.yaml
deleted file mode 100644
index a12206b..0000000
--- a/.github/workflows/bench.yaml
+++ /dev/null
@@ -1,38 +0,0 @@
-name: Benchmark
-
-on:
- pull_request:
- push:
- branches: [main]
-
-permissions:
- contents: write
- deployments: write
-
-jobs:
- benchmark:
- name: Run benchmarks
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
-
- - uses: actions/setup-python@v5
- with:
- python-version: "3.10"
-
- - name: Run benchmarks
- run: |
- pip install .[dev]
- pytest tests/bench.py --benchmark-json benchmark.json
-
- - name: Report results
- uses: benchmark-action/github-action-benchmark@v1
- with:
- name: Python Benchmarks
- tool: pytest
- output-file-path: benchmark.json
- github-token: ${{ secrets.GITHUB_TOKEN }}
- # Only update results if they are from main
- auto-push: ${{ github.ref == 'refs/heads/main' }}
- alert-threshold: "110%"
- comment-on-alert: true
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
deleted file mode 100644
index a64cd45..0000000
--- a/.github/workflows/ci.yaml
+++ /dev/null
@@ -1,88 +0,0 @@
-name: CI
-
-on:
- pull_request:
- push:
- branches: [main]
- tags: [v*.*.*]
-
-jobs:
- build:
- name: Test & Build
- strategy:
- matrix:
- python-version: ['3.7', '3.8', '3.10']
- image-variant: ['']
- include:
- - python-version: '2.7'
- image-variant: '-buster'
- runs-on: [ubuntu-latest]
- container:
- image: "python:${{ matrix.python-version }}${{ matrix.image-variant }}"
- env:
- PYTHON: ${{ matrix.python-version }}
- steps:
- - uses: actions/checkout@v4
- with:
- fetch-depth: 0 # fetch all history for setuptools_scm to be able to read tags
-
- - name: Install python dependencies
- run: |
- apt-get update
- apt-get -y install sudo
- pip install --upgrade pip
- sudo chown root .
- sudo -H pip install wheel build tox
- sudo -H pip install .[dev]
-
- - name: Determine pyenv
- id: pyenv
- run: echo "value=py$(echo $PYTHON | tr -d '.')" >> $GITHUB_OUTPUT
-
- - name: Run tests
- env:
- TOXENV: ${{ steps.pyenv.outputs.value }}
- run: tox
-
- - name: Build python package
- run: python -m build
-
- - name: Upload coverage
- uses: codecov/codecov-action@v5
- if: matrix.python-version == '3.10'
- with:
- token: ${{ secrets.CODECOV_TOKEN }}
- env_vars: PYTHON
- fail_ci_if_error: true
- files: .coverage.${{ steps.pyenv.outputs.value }}.xml
-
- - uses: actions/upload-artifact@v4
- if: matrix.python-version == '2.7' || matrix.python-version == '3.8'
- with:
- name: dist-${{ matrix.python-version }}
- path: dist
-
- publish:
- name: Publish to PyPI
- needs: build
- runs-on: [ubuntu-latest]
- permissions:
- id-token: write
- if: github.event_name != 'pull_request'
- steps:
- - uses: actions/download-artifact@v4
-
- - name: Organize files for upload
- run: |
- mkdir dist
- mv dist-3.8/* dist/
- mv dist-2.7/*.whl dist/
-
- - name: Test Publish package
- uses: pypa/gh-action-pypi-publish@release/v1
- with:
- repository-url: https://test.pypi.org/legacy/
-
- - name: Publish package
- uses: pypa/gh-action-pypi-publish@release/v1
- if: startsWith(github.event.ref, 'refs/tags/v')
diff --git a/.github/workflows/cla.yaml b/.github/workflows/cla.yaml
deleted file mode 100644
index fa180c6..0000000
--- a/.github/workflows/cla.yaml
+++ /dev/null
@@ -1,25 +0,0 @@
-name: Check CLA
-
-on:
- issue_comment:
- types: [created]
- pull_request_target:
- types: [opened, closed, synchronize]
-
-jobs:
- cla:
- name: Check CLA
- runs-on: ubuntu-latest
- steps:
- - name: CLA Assistant
- if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target'
- uses: secondlife-3p/contributor-assistant@v2
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- PERSONAL_ACCESS_TOKEN: ${{ secrets.SHARED_CLA_TOKEN }}
- with:
- branch: main
- path-to-document: https://github.com/secondlife/cla/blob/master/CLA.md
- path-to-signatures: signatures.json
- remote-organization-name: secondlife
- remote-repository-name: cla-signatures
diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 86fcbe9..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,287 +0,0 @@
-# Created by https://www.toptal.com/developers/gitignore/api/python,linux,windows,macos,vim,visualstudiocode
-# Edit at https://www.toptal.com/developers/gitignore?templates=python,linux,windows,macos,vim,visualstudiocode
-
-### Linux ###
-*~
-
-# temporary files which can be created if a process still has a handle open of a deleted file
-.fuse_hidden*
-
-# KDE directory preferences
-.directory
-
-# Linux trash folder which might appear on any partition or disk
-.Trash-*
-
-# .nfs files are created when an open file is removed but is still being accessed
-.nfs*
-
-### macOS ###
-# General
-.DS_Store
-.AppleDouble
-.LSOverride
-
-# Icon must end with two \r
-Icon
-
-
-# Thumbnails
-._*
-
-# Files that might appear in the root of a volume
-.DocumentRevisions-V100
-.fseventsd
-.Spotlight-V100
-.TemporaryItems
-.Trashes
-.VolumeIcon.icns
-.com.apple.timemachine.donotpresent
-
-# Directories potentially created on remote AFP share
-.AppleDB
-.AppleDesktop
-Network Trash Folder
-Temporary Items
-.apdisk
-
-### macOS Patch ###
-# iCloud generated files
-*.icloud
-
-### Python ###
-# Byte-compiled / optimized / DLL files
-__pycache__/
-*.py[cod]
-*$py.class
-
-# C extensions
-*.so
-
-# Distribution / packaging
-.Python
-build/
-develop-eggs/
-dist/
-downloads/
-eggs/
-.eggs/
-lib/
-lib64/
-parts/
-sdist/
-var/
-wheels/
-share/python-wheels/
-*.egg-info/
-.installed.cfg
-*.egg
-MANIFEST
-
-# PyInstaller
-# Usually these files are written by a python script from a template
-# before PyInstaller builds the exe, so as to inject date/other infos into it.
-*.manifest
-*.spec
-
-# Installer logs
-pip-log.txt
-pip-delete-this-directory.txt
-
-# Unit test / coverage reports
-htmlcov/
-.tox/
-.nox/
-.coverage
-.coverage.*
-.cache
-nosetests.xml
-coverage.xml
-*.cover
-*.py,cover
-.hypothesis/
-.pytest_cache/
-cover/
-
-# Translations
-*.mo
-*.pot
-
-# Django stuff:
-*.log
-local_settings.py
-db.sqlite3
-db.sqlite3-journal
-
-# Flask stuff:
-instance/
-.webassets-cache
-
-# Scrapy stuff:
-.scrapy
-
-# Sphinx documentation
-docs/_build/
-
-# PyBuilder
-.pybuilder/
-target/
-
-# Jupyter Notebook
-.ipynb_checkpoints
-
-# IPython
-profile_default/
-ipython_config.py
-
-# pyenv
-# For a library or package, you might want to ignore these files since the code is
-# intended to run in multiple environments; otherwise, check them in:
-# .python-version
-
-# pipenv
-# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
-# However, in case of collaboration, if having platform-specific dependencies or dependencies
-# having no cross-platform support, pipenv may install dependencies that don't work, or not
-# install all needed dependencies.
-#Pipfile.lock
-
-# poetry
-# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
-# This is especially recommended for binary packages to ensure reproducibility, and is more
-# commonly ignored for libraries.
-# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
-#poetry.lock
-
-# pdm
-# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
-#pdm.lock
-# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
-# in version control.
-# https://pdm.fming.dev/#use-with-ide
-.pdm.toml
-
-# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
-__pypackages__/
-
-# Celery stuff
-celerybeat-schedule
-celerybeat.pid
-
-# SageMath parsed files
-*.sage.py
-
-# Environments
-.env
-.venv
-env/
-venv/
-ENV/
-env.bak/
-venv.bak/
-
-# Spyder project settings
-.spyderproject
-.spyproject
-
-# Rope project settings
-.ropeproject
-
-# mkdocs documentation
-/site
-
-# mypy
-.mypy_cache/
-.dmypy.json
-dmypy.json
-
-# Pyre type checker
-.pyre/
-
-# pytype static type analyzer
-.pytype/
-
-# Cython debug symbols
-cython_debug/
-
-# PyCharm
-# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
-# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
-# and can be added to the global gitignore or merged into this file. For a more nuclear
-# option (not recommended) you can uncomment the following to ignore the entire idea folder.
-#.idea/
-
-### Vim ###
-# Swap
-[._]*.s[a-v][a-z]
-!*.svg # comment out if you don't need vector files
-[._]*.sw[a-p]
-[._]s[a-rt-v][a-z]
-[._]ss[a-gi-z]
-[._]sw[a-p]
-
-# Session
-Session.vim
-Sessionx.vim
-
-# Temporary
-.netrwhist
-# Auto-generated tag files
-tags
-# Persistent undo
-[._]*.un~
-
-### VisualStudioCode ###
-.vscode/*
-!.vscode/settings.json
-!.vscode/tasks.json
-!.vscode/launch.json
-!.vscode/extensions.json
-!.vscode/*.code-snippets
-
-# Local History for Visual Studio Code
-.history/
-
-# Built Visual Studio Code Extensions
-*.vsix
-
-### VisualStudioCode Patch ###
-# Ignore all local history of files
-.history
-.ionide
-
-# Support for Project snippet scope
-.vscode/*.code-snippets
-
-# Ignore code-workspaces
-*.code-workspace
-
-### Windows ###
-# Windows thumbnail cache files
-Thumbs.db
-Thumbs.db:encryptable
-ehthumbs.db
-ehthumbs_vista.db
-
-# Dump file
-*.stackdump
-
-# Folder config file
-[Dd]esktop.ini
-
-# Recycle Bin used on file shares
-$RECYCLE.BIN/
-
-# Windows Installer files
-*.cab
-*.msi
-*.msix
-*.msm
-*.msp
-
-# Windows shortcuts
-*.lnk
-
-# End of https://www.toptal.com/developers/gitignore/api/python,linux,windows,macos,vim,visualstudiocode
-
-.benchmarks/
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
deleted file mode 100644
index fae0520..0000000
--- a/.pre-commit-config.yaml
+++ /dev/null
@@ -1,21 +0,0 @@
-repos:
-- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v4.6.0
- hooks:
- - id: check-ast
- - id: check-yaml
- - id: mixed-line-ending
- - id: trailing-whitespace
-- repo: https://github.com/pycqa/isort
- rev: 5.13.2
- hooks:
- - id: isort
- args: [--line-length=120]
-- repo: local
- hooks:
- - id: test
- name: run pytest
- language: system
- entry: pytest
- pass_filenames: false
- types: [python]
\ No newline at end of file
diff --git a/CREDITS.md b/CREDITS.md
deleted file mode 100644
index df3f841..0000000
--- a/CREDITS.md
+++ /dev/null
@@ -1,4 +0,0 @@
-# Credits
-
-Thanks to [Tao Takashi](https://github.com/mrtopf) for
-the llsd PyPI package name.
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 9d14f49..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,19 +0,0 @@
-Copyright (c) 2006 Linden Research, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-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.
diff --git a/README.md b/README.md
deleted file mode 100644
index 829b739..0000000
--- a/README.md
+++ /dev/null
@@ -1,62 +0,0 @@
-# llsd
-
-[](https://codecov.io/gh/secondlife/python-llsd)
-
-Official python serialization library for [Linden Lab Structured Data (LLSD)][llsd].
-
-## Use
-
-Install **llsd** with pip:
-```
-pip install llsd
-```
-
-Use **llsd** to parse/format your data:
-```py
-import llsd
-
-data = {"foo": "bar"}
-
-# Format
-
-data_xml = llsd.format_xml(data)
-# >>> 'foo bar '
-data_notation = llsd.format_notation(data)
-# >>> "{'foo':'bar'}"
-data_binary = llsd.format_binary(data)
-# >>> '\n{\x00\x00\x00\x01k\x00\x00\x00\x03foos\x00\x00\x00\x03bar}'
-
-# Parse
-
-data = llsd.parse(data_xml)
-# >>> {'foo: 'bar'}
-data = llsd.parse(data_notation)
-# >>> {'foo: 'bar'}
-data = llsd.parse(data_binary)
-# >>> {'foo: 'bar'}
-```
-
-## Develop
-
-Requirements:
-
-- [pre-commit](https://pre-commit.com/)
-
-Set up a venv and install development dependencies:
-```
-python3 -m venv .venv
-. .venv/bin/activate
-pip install .[dev]
-```
-
-Run tests:
-```
-pytest
-```
-
-### Benchmarks
-
-Benchmarks from commits to `main` are published [here](https://secondlife.github.io/python-llsd/dev/bench/).
-
-[llsd]: https://wiki.secondlife.com/wiki/LLSD
-[llbase]: https://pypi.org/project/llbase/
diff --git a/dev/bench/data.js b/dev/bench/data.js
new file mode 100644
index 0000000..543db0a
--- /dev/null
+++ b/dev/bench/data.js
@@ -0,0 +1,2117 @@
+window.BENCHMARK_DATA = {
+ "lastUpdate": 1742056357911,
+ "repoUrl": "https://github.com/secondlife/python-llsd",
+ "entries": {
+ "Python Benchmarks": [
+ {
+ "commit": {
+ "author": {
+ "email": "signal@lindenlab.com",
+ "name": "Signal Linden",
+ "username": "bennettgoble"
+ },
+ "committer": {
+ "email": "noreply@github.com",
+ "name": "GitHub",
+ "username": "web-flow"
+ },
+ "distinct": true,
+ "id": "8f5fabab741e3427f85be880d28af5cb9dcfc353",
+ "message": "Merge pull request #10 from secondlife/signal/bench-summary\n\nPublish benchmarks in job summary",
+ "timestamp": "2023-03-16T12:51:09-07:00",
+ "tree_id": "f8f2a6eef383b51ca5c29485a3ac2bc7d9609009",
+ "url": "https://github.com/secondlife/python-llsd/commit/8f5fabab741e3427f85be880d28af5cb9dcfc353"
+ },
+ "date": 1678996298253,
+ "tool": "pytest",
+ "benches": [
+ {
+ "name": "tests/bench.py::test_parse_xml_stream",
+ "value": 12872.181812208772,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0000022186791421610883",
+ "extra": "mean: 77.68690767337813 usec\nrounds: 4874"
+ },
+ {
+ "name": "tests/bench.py::test_parse_notation_stream",
+ "value": 2205.4076588476173,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00019966932409915566",
+ "extra": "mean: 453.43090924175266 usec\nrounds: 1807"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_stream",
+ "value": 12166.264529452834,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00003357310024603729",
+ "extra": "mean: 82.19449754517001 usec\nrounds: 7740"
+ },
+ {
+ "name": "tests/bench.py::test_parse_notation_bytes",
+ "value": 4002.991825681371,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00003568834188397126",
+ "extra": "mean: 249.81315065008522 usec\nrounds: 3153"
+ },
+ {
+ "name": "tests/bench.py::test_parse_xml_bytes",
+ "value": 13982.993986334646,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0000017384725864036928",
+ "extra": "mean: 71.5154423278222 usec\nrounds: 6667"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_bytes",
+ "value": 14578.919949218085,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00003596055356104874",
+ "extra": "mean: 68.59218676577159 usec\nrounds: 8765"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml",
+ "value": 14470.950234925818,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0000017050134935794276",
+ "extra": "mean: 69.10396233596931 usec\nrounds: 7381"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation",
+ "value": 24882.69811579331,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000014272846192442663",
+ "extra": "mean: 40.18856778900876 usec\nrounds: 2198"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary",
+ "value": 26489.816812509813,
+ "unit": "iter/sec",
+ "range": "stddev: 9.922669037536676e-7",
+ "extra": "mean: 37.75035543196925 usec\nrounds: 11313"
+ }
+ ]
+ },
+ {
+ "commit": {
+ "author": {
+ "email": "signal@lindenlab.com",
+ "name": "Signal Linden",
+ "username": "bennettgoble"
+ },
+ "committer": {
+ "email": "noreply@github.com",
+ "name": "GitHub",
+ "username": "web-flow"
+ },
+ "distinct": true,
+ "id": "438e41d47687af3040be60a73f01f80cb7c5009a",
+ "message": "Merge pull request #9 from secondlife/sl-18330-fix\n\nSL-18830: Fix sporadic notation parse failure with very large input.",
+ "timestamp": "2023-03-16T13:02:10-07:00",
+ "tree_id": "d6af6f478047eb93b3f084e047405efb7302c204",
+ "url": "https://github.com/secondlife/python-llsd/commit/438e41d47687af3040be60a73f01f80cb7c5009a"
+ },
+ "date": 1678996960629,
+ "tool": "pytest",
+ "benches": [
+ {
+ "name": "tests/bench.py::test_parse_xml_stream",
+ "value": 12495.159989307285,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000001796551337468087",
+ "extra": "mean: 80.03098806703944 usec\nrounds: 4609"
+ },
+ {
+ "name": "tests/bench.py::test_parse_notation_stream",
+ "value": 3009.6538886291164,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00021585645151115033",
+ "extra": "mean: 332.26411973088886 usec\nrounds: 2230"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_stream",
+ "value": 13524.361867793872,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000031128561715433327",
+ "extra": "mean: 73.9406420632194 usec\nrounds: 8278"
+ },
+ {
+ "name": "tests/bench.py::test_parse_notation_bytes",
+ "value": 3703.0402892099933,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00003487006193489698",
+ "extra": "mean: 270.0483715810016 usec\nrounds: 2998"
+ },
+ {
+ "name": "tests/bench.py::test_parse_xml_bytes",
+ "value": 13713.750342074072,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0000020156423101261827",
+ "extra": "mean: 72.91951326632942 usec\nrounds: 6671"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_bytes",
+ "value": 14466.237302542444,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00003324372179853647",
+ "extra": "mean: 69.12647560566766 usec\nrounds: 8547"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml",
+ "value": 15020.580807426615,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0000012655967514258396",
+ "extra": "mean: 66.57532174159142 usec\nrounds: 7189"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation",
+ "value": 25999.305531143098,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000013443974619298474",
+ "extra": "mean: 38.462565809773515 usec\nrounds: 12331"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary",
+ "value": 26090.624414662354,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0000010597874351514089",
+ "extra": "mean: 38.3279443261627 usec\nrounds: 11262"
+ }
+ ]
+ },
+ {
+ "commit": {
+ "author": {
+ "email": "nat@lindenlab.com",
+ "name": "nat-goodspeed",
+ "username": "nat-goodspeed"
+ },
+ "committer": {
+ "email": "noreply@github.com",
+ "name": "GitHub",
+ "username": "web-flow"
+ },
+ "distinct": true,
+ "id": "c4035fb6ed54bafbb968d778a0e9fa60cb65e74f",
+ "message": "Merge pull request #11 from secondlife/signal/bench-readme\n\nAdd basic development instructions",
+ "timestamp": "2023-03-16T17:20:51-04:00",
+ "tree_id": "a9a8fad2902645e32f4cf61fbcceb95ec10df74a",
+ "url": "https://github.com/secondlife/python-llsd/commit/c4035fb6ed54bafbb968d778a0e9fa60cb65e74f"
+ },
+ "date": 1679001686035,
+ "tool": "pytest",
+ "benches": [
+ {
+ "name": "tests/bench.py::test_parse_xml_stream",
+ "value": 8300.473669688761,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00005706394950755007",
+ "extra": "mean: 120.47505236378835 usec\nrounds: 3342"
+ },
+ {
+ "name": "tests/bench.py::test_parse_notation_stream",
+ "value": 2170.2928269190556,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00029043219624840633",
+ "extra": "mean: 460.76731563436005 usec\nrounds: 1695"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_stream",
+ "value": 9755.97508852484,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00006527358784005084",
+ "extra": "mean: 102.50128674233892 usec\nrounds: 5280"
+ },
+ {
+ "name": "tests/bench.py::test_parse_notation_bytes",
+ "value": 2657.2559583178227,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0001100800966197872",
+ "extra": "mean: 376.32806763299175 usec\nrounds: 1863"
+ },
+ {
+ "name": "tests/bench.py::test_parse_xml_bytes",
+ "value": 9057.213634529715,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000060535948325585013",
+ "extra": "mean: 110.40923184008828 usec\nrounds: 5603"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_bytes",
+ "value": 10356.718680816699,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00006844433281053462",
+ "extra": "mean: 96.55567857146266 usec\nrounds: 6216"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml",
+ "value": 10817.987785820233,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00005813904804121425",
+ "extra": "mean: 92.43863274746514 usec\nrounds: 2162"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation",
+ "value": 18440.266312430256,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000051923028874614916",
+ "extra": "mean: 54.229151740933254 usec\nrounds: 10742"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary",
+ "value": 18598.440988295966,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00003668074092684782",
+ "extra": "mean: 53.76794757309508 usec\nrounds: 9785"
+ }
+ ]
+ },
+ {
+ "commit": {
+ "author": {
+ "email": "nat@lindenlab.com",
+ "name": "nat-goodspeed",
+ "username": "nat-goodspeed"
+ },
+ "committer": {
+ "email": "noreply@github.com",
+ "name": "GitHub",
+ "username": "web-flow"
+ },
+ "distinct": true,
+ "id": "0adae956ed43a09d71d7200b11eec525a6d7b0d6",
+ "message": "Merge pull request #5 from secondlife/sl-19314\n\nSL-19314: Recast llsd serialization to write to a stream.",
+ "timestamp": "2023-03-20T14:41:09-04:00",
+ "tree_id": "b553a8ff4e2aa4d7c664e0fd49b42f534965f057",
+ "url": "https://github.com/secondlife/python-llsd/commit/0adae956ed43a09d71d7200b11eec525a6d7b0d6"
+ },
+ "date": 1679337702394,
+ "tool": "pytest",
+ "benches": [
+ {
+ "name": "tests/bench.py::test_parse_xml_stream",
+ "value": 10141.084204071363,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00006546413149893282",
+ "extra": "mean: 98.60878579417847 usec\nrounds: 3590"
+ },
+ {
+ "name": "tests/bench.py::test_parse_notation_stream",
+ "value": 2451.860006533864,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0003483534560991509",
+ "extra": "mean: 407.8536284025759 usec\nrounds: 1690"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_stream",
+ "value": 10133.009280781782,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0001688658022580344",
+ "extra": "mean: 98.68736643679932 usec\nrounds: 6817"
+ },
+ {
+ "name": "tests/bench.py::test_parse_notation_bytes",
+ "value": 2854.595266990118,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0002153905641903825",
+ "extra": "mean: 350.3123583100447 usec\nrounds: 2509"
+ },
+ {
+ "name": "tests/bench.py::test_parse_xml_bytes",
+ "value": 10584.71309520326,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00015353939907668615",
+ "extra": "mean: 94.4758720435395 usec\nrounds: 930"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_bytes",
+ "value": 11095.315584964033,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00016813694472493784",
+ "extra": "mean: 90.12812590523909 usec\nrounds: 7593"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml",
+ "value": 10565.237942231777,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00008288246169716064",
+ "extra": "mean: 94.65002165287365 usec\nrounds: 1755"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation",
+ "value": 20531.269478147016,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00004856970267587009",
+ "extra": "mean: 48.706194279139716 usec\nrounds: 10593"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary",
+ "value": 19827.7841545781,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00007648882122992257",
+ "extra": "mean: 50.43427910067837 usec\nrounds: 9785"
+ }
+ ]
+ },
+ {
+ "commit": {
+ "author": {
+ "email": "nat@lindenlab.com",
+ "name": "nat-goodspeed",
+ "username": "nat-goodspeed"
+ },
+ "committer": {
+ "email": "noreply@github.com",
+ "name": "GitHub",
+ "username": "web-flow"
+ },
+ "distinct": true,
+ "id": "09310464c7c5ec5df260a151ed191d2a72898d9c",
+ "message": "Merge pull request #6 from secondlife/sl-18330-perf\n\nSL-18330: Refactor notation parsing to manage a lookahead char.",
+ "timestamp": "2023-03-22T16:36:50-04:00",
+ "tree_id": "48e9a5ffd5491d9afb542d5dcc3b3b6daa3e7638",
+ "url": "https://github.com/secondlife/python-llsd/commit/09310464c7c5ec5df260a151ed191d2a72898d9c"
+ },
+ "date": 1679517446149,
+ "tool": "pytest",
+ "benches": [
+ {
+ "name": "tests/bench.py::test_parse_xml_stream",
+ "value": 12909.923296042954,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0000015962367173426108",
+ "extra": "mean: 77.45979407224766 usec\nrounds: 4521"
+ },
+ {
+ "name": "tests/bench.py::test_parse_notation_stream",
+ "value": 4227.471582622453,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00017779182856725737",
+ "extra": "mean: 236.54801231795955 usec\nrounds: 2192"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_stream",
+ "value": 15563.761914953298,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000042570073606750205",
+ "extra": "mean: 64.2518181314007 usec\nrounds: 9001"
+ },
+ {
+ "name": "tests/bench.py::test_parse_notation_bytes",
+ "value": 4641.493022455551,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000029440320878755105",
+ "extra": "mean: 215.44791625496327 usec\nrounds: 3642"
+ },
+ {
+ "name": "tests/bench.py::test_parse_xml_bytes",
+ "value": 15632.688204563447,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0000013954437107169295",
+ "extra": "mean: 63.96852460142351 usec\nrounds: 7337"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_bytes",
+ "value": 17080.303553675392,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00003450061722708274",
+ "extra": "mean: 58.54696884381875 usec\nrounds: 10977"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml",
+ "value": 13383.90740274769,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000013177191563706168",
+ "extra": "mean: 74.71659582721723 usec\nrounds: 6950"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation",
+ "value": 25066.830254749835,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000013077455730759876",
+ "extra": "mean: 39.893356672430215 usec\nrounds: 13211"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary",
+ "value": 26214.91177645831,
+ "unit": "iter/sec",
+ "range": "stddev: 8.712771456782391e-7",
+ "extra": "mean: 38.146227938025206 usec\nrounds: 11683"
+ }
+ ]
+ },
+ {
+ "commit": {
+ "author": {
+ "email": "signal@lindenlab.com",
+ "name": "Signal Linden",
+ "username": "bennettgoble"
+ },
+ "committer": {
+ "email": "noreply@github.com",
+ "name": "GitHub",
+ "username": "web-flow"
+ },
+ "distinct": true,
+ "id": "ed393fde08e3669bbc9d2d9214aa10e1022b2563",
+ "message": "Add PyPI trusted publication (#12)\n\nAdd PyPI trusted publication\r\n\r\nPublish llsd with PyPI's new [trusted publisher](https://blog.pypi.org/posts/2023-04-20-introducing-trusted-publishers/) functionality rather than an access token.",
+ "timestamp": "2023-04-21T10:39:22-07:00",
+ "tree_id": "b9dc9d85eba28f2b9b1ed09b6201cb3b42838560",
+ "url": "https://github.com/secondlife/python-llsd/commit/ed393fde08e3669bbc9d2d9214aa10e1022b2563"
+ },
+ "date": 1682098796079,
+ "tool": "pytest",
+ "benches": [
+ {
+ "name": "tests/bench.py::test_parse_xml_stream",
+ "value": 8401.410233480117,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000028143593606264825",
+ "extra": "mean: 119.02763610029906 usec\nrounds: 3108"
+ },
+ {
+ "name": "tests/bench.py::test_parse_notation_stream",
+ "value": 3103.4882017496516,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0002465618766434401",
+ "extra": "mean: 322.2180768840141 usec\nrounds: 1964"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_stream",
+ "value": 11845.999955317911,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00007200932853574851",
+ "extra": "mean: 84.41668105452588 usec\nrounds: 5653"
+ },
+ {
+ "name": "tests/bench.py::test_parse_notation_bytes",
+ "value": 3598.045609310651,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00008768229864581673",
+ "extra": "mean: 277.9286614411733 usec\nrounds: 3317"
+ },
+ {
+ "name": "tests/bench.py::test_parse_xml_bytes",
+ "value": 9989.97967818425,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00005278396556448257",
+ "extra": "mean: 100.10030372571859 usec\nrounds: 2657"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_bytes",
+ "value": 14149.262982134755,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000047877897681145966",
+ "extra": "mean: 70.67505927783147 usec\nrounds: 8418"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml",
+ "value": 10445.428648020821,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000033306463552091626",
+ "extra": "mean: 95.73565946376723 usec\nrounds: 4998"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation",
+ "value": 20189.290617260536,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00002340255990154317",
+ "extra": "mean: 49.53121033113787 usec\nrounds: 8905"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary",
+ "value": 21068.91781205809,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000019710617091594125",
+ "extra": "mean: 47.46328259098734 usec\nrounds: 10977"
+ }
+ ]
+ },
+ {
+ "commit": {
+ "author": {
+ "email": "signal@lindenlab.com",
+ "name": "Signal Linden",
+ "username": "bennettgoble"
+ },
+ "committer": {
+ "email": "noreply@github.com",
+ "name": "GitHub",
+ "username": "web-flow"
+ },
+ "distinct": true,
+ "id": "46fdce0be06eb90cc2bf0bb4d1736cd81844b890",
+ "message": "Switch PyPI action param case to kebab\n\nFixes deprecation warning about repository_url.",
+ "timestamp": "2023-05-04T12:36:02-07:00",
+ "tree_id": "e77533ea846462ef801ec06f8ad47aa995ba4a5e",
+ "url": "https://github.com/secondlife/python-llsd/commit/46fdce0be06eb90cc2bf0bb4d1736cd81844b890"
+ },
+ "date": 1683228996474,
+ "tool": "pytest",
+ "benches": [
+ {
+ "name": "tests/bench.py::test_parse_xml_stream",
+ "value": 8596.225166748598,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00005808476456724832",
+ "extra": "mean: 116.33013102869153 usec\nrounds: 3587"
+ },
+ {
+ "name": "tests/bench.py::test_parse_notation_stream",
+ "value": 3215.5453601785107,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0002668789446984807",
+ "extra": "mean: 310.98923759062916 usec\nrounds: 1793"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_stream",
+ "value": 12292.815169082878,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0000753499327366744",
+ "extra": "mean: 81.34833121993539 usec\nrounds: 7886"
+ },
+ {
+ "name": "tests/bench.py::test_parse_notation_bytes",
+ "value": 3697.3929771043913,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00014229848015188685",
+ "extra": "mean: 270.4608371878146 usec\nrounds: 3243"
+ },
+ {
+ "name": "tests/bench.py::test_parse_xml_bytes",
+ "value": 11152.30995060082,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00007596157896915804",
+ "extra": "mean: 89.66752219311533 usec\nrounds: 6511"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_bytes",
+ "value": 14294.424712368927,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000058709002444133834",
+ "extra": "mean: 69.95734491747 usec\nrounds: 8834"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml",
+ "value": 11150.297285691477,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00005536912357994805",
+ "extra": "mean: 89.68370747237758 usec\nrounds: 5179"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation",
+ "value": 21237.79814122248,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00003803726295527947",
+ "extra": "mean: 47.085860471524306 usec\nrounds: 10858"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary",
+ "value": 21154.097004896656,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000040814894197669976",
+ "extra": "mean: 47.27216669983712 usec\nrounds: 10030"
+ }
+ ]
+ },
+ {
+ "commit": {
+ "author": {
+ "email": "nat@lindenlab.com",
+ "name": "nat-goodspeed",
+ "username": "nat-goodspeed"
+ },
+ "committer": {
+ "email": "noreply@github.com",
+ "name": "GitHub",
+ "username": "web-flow"
+ },
+ "distinct": true,
+ "id": "a63abbef1ed29c4e750529854b7f2c43fbe360b8",
+ "message": "Merge pull request #13 from secondlife/log/deep_map\n\nSL-18330: In XML formatter, avoid adding call stack depth.",
+ "timestamp": "2023-05-08T10:13:57-04:00",
+ "tree_id": "c9e8fa449ffcd8dd71fb48e9d3daddac89f3c115",
+ "url": "https://github.com/secondlife/python-llsd/commit/a63abbef1ed29c4e750529854b7f2c43fbe360b8"
+ },
+ "date": 1683555267712,
+ "tool": "pytest",
+ "benches": [
+ {
+ "name": "tests/bench.py::test_parse_xml_stream",
+ "value": 12385.13965525791,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000003357671187857512",
+ "extra": "mean: 80.74192361452026 usec\nrounds: 4294"
+ },
+ {
+ "name": "tests/bench.py::test_parse_notation_stream",
+ "value": 4316.033655275787,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00017824729524758487",
+ "extra": "mean: 231.69420812500633 usec\nrounds: 2806"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_stream",
+ "value": 15655.984973123714,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000030265184103295064",
+ "extra": "mean: 63.87333672820191 usec\nrounds: 9524"
+ },
+ {
+ "name": "tests/bench.py::test_parse_notation_bytes",
+ "value": 4713.246069957984,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00002772524407139972",
+ "extra": "mean: 212.16800166109607 usec\nrounds: 3612"
+ },
+ {
+ "name": "tests/bench.py::test_parse_xml_bytes",
+ "value": 14963.893650457858,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0000016281721266114382",
+ "extra": "mean: 66.8275265354751 usec\nrounds: 3109"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_bytes",
+ "value": 17550.267383165712,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00003116645055969604",
+ "extra": "mean: 56.979188873168056 usec\nrounds: 10515"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml",
+ "value": 17118.960322648418,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000012240580240138473",
+ "extra": "mean: 58.41476241270318 usec\nrounds: 8439"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation",
+ "value": 26326.55225540916,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000011888050812629382",
+ "extra": "mean: 37.984464896824306 usec\nrounds: 9643"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary",
+ "value": 25760.089405910738,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000001149915234740709",
+ "extra": "mean: 38.81974104369944 usec\nrounds: 11249"
+ }
+ ]
+ },
+ {
+ "commit": {
+ "author": {
+ "email": "roxanne@roxiware.com",
+ "name": "Roxanne Skelly",
+ "username": "roxanneskelly"
+ },
+ "committer": {
+ "email": "noreply@github.com",
+ "name": "GitHub",
+ "username": "web-flow"
+ },
+ "distinct": true,
+ "id": "b703873ef2f5e09155b5d6e58e841145437a3c27",
+ "message": "Merge pull request #15 from secondlife/SRV-439\n\nSRV-439 - performance optimizations for string handling in xml formatting",
+ "timestamp": "2023-09-07T13:13:19-07:00",
+ "tree_id": "90faa284611ea2757c433e5d983d07c90b32965f",
+ "url": "https://github.com/secondlife/python-llsd/commit/b703873ef2f5e09155b5d6e58e841145437a3c27"
+ },
+ "date": 1694117688208,
+ "tool": "pytest",
+ "benches": [
+ {
+ "name": "tests/bench.py::test_parse_xml_stream",
+ "value": 12400.876930837765,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0000020154217057357803",
+ "extra": "mean: 80.63945844936653 usec\nrounds: 4308"
+ },
+ {
+ "name": "tests/bench.py::test_parse_notation_stream",
+ "value": 4285.042083926906,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00002688969382671492",
+ "extra": "mean: 233.36993672733738 usec\nrounds: 2750"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_stream",
+ "value": 15502.002579149737,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00003278538982642423",
+ "extra": "mean: 64.50779471195575 usec\nrounds: 8510"
+ },
+ {
+ "name": "tests/bench.py::test_parse_notation_bytes",
+ "value": 4608.93699067061,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00002849527827174635",
+ "extra": "mean: 216.96977025813015 usec\nrounds: 3517"
+ },
+ {
+ "name": "tests/bench.py::test_parse_xml_bytes",
+ "value": 15178.721126042934,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0000015114742756373176",
+ "extra": "mean: 65.88170318804048 usec\nrounds: 7183"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_bytes",
+ "value": 16951.5580969395,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00003407958627938856",
+ "extra": "mean: 58.99162745285012 usec\nrounds: 10039"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml",
+ "value": 19329.48894091656,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00001291174012510934",
+ "extra": "mean: 51.73442521199851 usec\nrounds: 7782"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation",
+ "value": 23281.178240620364,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000012682945522827392",
+ "extra": "mean: 42.95315252796043 usec\nrounds: 10503"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary",
+ "value": 25350.441553605502,
+ "unit": "iter/sec",
+ "range": "stddev: 9.170085610769461e-7",
+ "extra": "mean: 39.44704465543219 usec\nrounds: 11376"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml_deep",
+ "value": 220.80638639515766,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00006939136434361314",
+ "extra": "mean: 4.528854515151516 msec\nrounds: 198"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml_wide",
+ "value": 0.5439629781791014,
+ "unit": "iter/sec",
+ "range": "stddev: 0.004288264931640944",
+ "extra": "mean: 1.838360403400003 sec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation_deep",
+ "value": 282.30209368668704,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000037876346844994716",
+ "extra": "mean: 3.54230458209017 msec\nrounds: 268"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation_wide",
+ "value": 0.6950752910135733,
+ "unit": "iter/sec",
+ "range": "stddev: 0.004344220335527082",
+ "extra": "mean: 1.4386930638000082 sec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation_wide_array",
+ "value": 1.1267186085687908,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0021471007159548573",
+ "extra": "mean: 887.5330471999973 msec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary_deep",
+ "value": 250.0105358877701,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000007938472069168623",
+ "extra": "mean: 3.999831432899695 msec\nrounds: 231"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary_wide",
+ "value": 0.6229985032994216,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0011434795723045251",
+ "extra": "mean: 1.6051402928000074 sec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary_wide_array",
+ "value": 0.8591906594760393,
+ "unit": "iter/sec",
+ "range": "stddev: 0.006885452751917601",
+ "extra": "mean: 1.1638860234000106 sec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_parse_xml_deep",
+ "value": 257.7893561696026,
+ "unit": "iter/sec",
+ "range": "stddev: 0.005908778845637322",
+ "extra": "mean: 3.8791361088705627 msec\nrounds: 248"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_deep",
+ "value": 202.06927819673965,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000034898422119658154",
+ "extra": "mean: 4.948797803030579 msec\nrounds: 198"
+ }
+ ]
+ },
+ {
+ "commit": {
+ "author": {
+ "email": "nat@lindenlab.com",
+ "name": "nat-goodspeed",
+ "username": "nat-goodspeed"
+ },
+ "committer": {
+ "email": "noreply@github.com",
+ "name": "GitHub",
+ "username": "web-flow"
+ },
+ "distinct": true,
+ "id": "9655ab4629c37881b223060972a1155d4c4f58e0",
+ "message": "Merge pull request #16 from secondlife/dependabot/github_actions/actions/checkout-4\n\nBump actions/checkout from 3 to 4",
+ "timestamp": "2023-10-05T17:21:08-04:00",
+ "tree_id": "5784caaeff5a07eb18d6fe83495cfacf54e70c3c",
+ "url": "https://github.com/secondlife/python-llsd/commit/9655ab4629c37881b223060972a1155d4c4f58e0"
+ },
+ "date": 1696540958005,
+ "tool": "pytest",
+ "benches": [
+ {
+ "name": "tests/bench.py::test_parse_xml_stream",
+ "value": 11892.318545601172,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000001939030663054047",
+ "extra": "mean: 84.08789221088331 usec\nrounds: 3980"
+ },
+ {
+ "name": "tests/bench.py::test_parse_notation_stream",
+ "value": 4015.1881579431906,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00005715691360910909",
+ "extra": "mean: 249.0543308715717 usec\nrounds: 2708"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_stream",
+ "value": 14850.95786138028,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00003053199286817588",
+ "extra": "mean: 67.33572402090553 usec\nrounds: 8555"
+ },
+ {
+ "name": "tests/bench.py::test_parse_notation_bytes",
+ "value": 4299.189034759652,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00002782497891442754",
+ "extra": "mean: 232.60200747509245 usec\nrounds: 3077"
+ },
+ {
+ "name": "tests/bench.py::test_parse_xml_bytes",
+ "value": 14303.536946792752,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0000036565118611130075",
+ "extra": "mean: 69.91277777796265 usec\nrounds: 6579"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_bytes",
+ "value": 16287.337742606274,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000031853820678365714",
+ "extra": "mean: 61.39738831497833 usec\nrounds: 8130"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml",
+ "value": 18583.04347717172,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000013046413893901367",
+ "extra": "mean: 53.81249854085779 usec\nrounds: 8224"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation",
+ "value": 22648.759081649958,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000012418730168823472",
+ "extra": "mean: 44.15252934586605 usec\nrounds: 9814"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary",
+ "value": 23782.58906357611,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0000024632024686721427",
+ "extra": "mean: 42.047566702127305 usec\nrounds: 11274"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml_deep",
+ "value": 208.88704459288252,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00010163733616835158",
+ "extra": "mean: 4.787276309782562 msec\nrounds: 184"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml_wide",
+ "value": 0.5155495379202011,
+ "unit": "iter/sec",
+ "range": "stddev: 0.007611663073909226",
+ "extra": "mean: 1.9396778126000072 sec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation_deep",
+ "value": 265.2713558123921,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000060017055098687275",
+ "extra": "mean: 3.7697247670691976 msec\nrounds: 249"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation_wide",
+ "value": 0.662776814607169,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0010740100628152446",
+ "extra": "mean: 1.508803533799994 sec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation_wide_array",
+ "value": 1.093607756147928,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0014775191073895769",
+ "extra": "mean: 914.4046339999932 msec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary_deep",
+ "value": 230.31163847318945,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000009700978028588764",
+ "extra": "mean: 4.3419429718329665 msec\nrounds: 213"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary_wide",
+ "value": 0.5639411660726928,
+ "unit": "iter/sec",
+ "range": "stddev: 0.007065359177845713",
+ "extra": "mean: 1.7732346212000039 sec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary_wide_array",
+ "value": 0.7780793318289493,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0014327402783182118",
+ "extra": "mean: 1.2852159915999892 sec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_parse_xml_deep",
+ "value": 278.1522972143162,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000026585225235979346",
+ "extra": "mean: 3.595152763485899 msec\nrounds: 241"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_deep",
+ "value": 193.76847420924514,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000037005842480491656",
+ "extra": "mean: 5.160798236560031 msec\nrounds: 186"
+ }
+ ]
+ },
+ {
+ "commit": {
+ "author": {
+ "email": "nat@lindenlab.com",
+ "name": "nat-goodspeed",
+ "username": "nat-goodspeed"
+ },
+ "committer": {
+ "email": "noreply@github.com",
+ "name": "GitHub",
+ "username": "web-flow"
+ },
+ "distinct": true,
+ "id": "6a83d7ffcf81b9be5ddb0ba32dfc529864901cc2",
+ "message": "Merge pull request #18 from secondlife/dependabot/github_actions/actions/setup-python-5\n\nBump actions/setup-python from 4 to 5",
+ "timestamp": "2024-01-02T17:03:40-05:00",
+ "tree_id": "3669117e04cb342e077caa8ea8a11a34cbf60f5a",
+ "url": "https://github.com/secondlife/python-llsd/commit/6a83d7ffcf81b9be5ddb0ba32dfc529864901cc2"
+ },
+ "date": 1704233093113,
+ "tool": "pytest",
+ "benches": [
+ {
+ "name": "tests/bench.py::test_parse_xml_stream",
+ "value": 15817.748850333048,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0000049454232572506185",
+ "extra": "mean: 63.220121236085035 usec\nrounds: 5015"
+ },
+ {
+ "name": "tests/bench.py::test_parse_notation_stream",
+ "value": 5226.305717036576,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000023195145688932988",
+ "extra": "mean: 191.33974438966055 usec\nrounds: 3654"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_stream",
+ "value": 19108.36290998745,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000027932258397521702",
+ "extra": "mean: 52.33310696005914 usec\nrounds: 3908"
+ },
+ {
+ "name": "tests/bench.py::test_parse_notation_bytes",
+ "value": 5589.144603128502,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000024681583520059786",
+ "extra": "mean: 178.91825511908456 usec\nrounds: 4786"
+ },
+ {
+ "name": "tests/bench.py::test_parse_xml_bytes",
+ "value": 18952.307873543115,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0000064658372761547725",
+ "extra": "mean: 52.76402254925225 usec\nrounds: 9446"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_bytes",
+ "value": 21056.190666146376,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000029203695454950567",
+ "extra": "mean: 47.49197116683481 usec\nrounds: 14081"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml",
+ "value": 24611.46043207338,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000010356354415810582",
+ "extra": "mean: 40.63147746798524 usec\nrounds: 11406"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation",
+ "value": 29878.910875172453,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000010185781869046188",
+ "extra": "mean: 33.46842206457193 usec\nrounds: 14095"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary",
+ "value": 31830.31941075389,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0000016043977631718027",
+ "extra": "mean: 31.41658703123631 usec\nrounds: 13679"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml_deep",
+ "value": 281.1184958242179,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0003743238945038085",
+ "extra": "mean: 3.5572188057853555 msec\nrounds: 242"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml_wide",
+ "value": 0.7273139787231522,
+ "unit": "iter/sec",
+ "range": "stddev: 0.015157278237429421",
+ "extra": "mean: 1.3749220133999984 sec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation_deep",
+ "value": 355.27013357330435,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00010387737303301474",
+ "extra": "mean: 2.81475954632608 msec\nrounds: 313"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation_wide",
+ "value": 0.9181573879351806,
+ "unit": "iter/sec",
+ "range": "stddev: 0.005372596694519276",
+ "extra": "mean: 1.089137889799997 sec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation_wide_array",
+ "value": 1.5495171175811437,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0068435045283850165",
+ "extra": "mean: 645.3623445999995 msec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary_deep",
+ "value": 307.0209478293415,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00009111088945665466",
+ "extra": "mean: 3.257106744898244 msec\nrounds: 294"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary_wide",
+ "value": 0.7866670063368922,
+ "unit": "iter/sec",
+ "range": "stddev: 0.013415616560735342",
+ "extra": "mean: 1.2711858918000019 sec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary_wide_array",
+ "value": 1.0968526390904527,
+ "unit": "iter/sec",
+ "range": "stddev: 0.008067776856191717",
+ "extra": "mean: 911.6994976000001 msec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_parse_xml_deep",
+ "value": 303.20488262798125,
+ "unit": "iter/sec",
+ "range": "stddev: 0.006690864989110339",
+ "extra": "mean: 3.298099922839814 msec\nrounds: 324"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_deep",
+ "value": 251.09686230482555,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000036038591848352536",
+ "extra": "mean: 3.982526865612618 msec\nrounds: 253"
+ }
+ ]
+ },
+ {
+ "commit": {
+ "author": {
+ "email": "nat@lindenlab.com",
+ "name": "nat-goodspeed",
+ "username": "nat-goodspeed"
+ },
+ "committer": {
+ "email": "noreply@github.com",
+ "name": "GitHub",
+ "username": "web-flow"
+ },
+ "distinct": true,
+ "id": "1b60fb99c5e343344cdd6436e63a74a0b6a46b4e",
+ "message": "Merge pull request #19 from secondlife/dependabot/github_actions/actions/download-artifact-4\n\nBump actions/download-artifact from 3 to 4",
+ "timestamp": "2024-01-02T17:04:14-05:00",
+ "tree_id": "79810cd2ef7929fef9a6bd62bfc0f003f88f5f09",
+ "url": "https://github.com/secondlife/python-llsd/commit/1b60fb99c5e343344cdd6436e63a74a0b6a46b4e"
+ },
+ "date": 1704233127821,
+ "tool": "pytest",
+ "benches": [
+ {
+ "name": "tests/bench.py::test_parse_xml_stream",
+ "value": 15771.481761552666,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0000035281675703742757",
+ "extra": "mean: 63.40558326217488 usec\nrounds: 4672"
+ },
+ {
+ "name": "tests/bench.py::test_parse_notation_stream",
+ "value": 5301.90037250154,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000023734886571667883",
+ "extra": "mean: 188.61161654159497 usec\nrounds: 3591"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_stream",
+ "value": 19579.96773007318,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000028930327560053272",
+ "extra": "mean: 51.07260715573521 usec\nrounds: 11124"
+ },
+ {
+ "name": "tests/bench.py::test_parse_notation_bytes",
+ "value": 5648.875129816638,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000024969177491298888",
+ "extra": "mean: 177.02639499352148 usec\nrounds: 2357"
+ },
+ {
+ "name": "tests/bench.py::test_parse_xml_bytes",
+ "value": 19468.970623761248,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0000028126786056716277",
+ "extra": "mean: 51.363783906455346 usec\nrounds: 8612"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_bytes",
+ "value": 21415.164843480532,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000029627572069086895",
+ "extra": "mean: 46.69588150774531 usec\nrounds: 14406"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml",
+ "value": 24692.406232870944,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00001093615219869209",
+ "extra": "mean: 40.4982807495198 usec\nrounds: 10675"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation",
+ "value": 30427.164021387784,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000010198318836456697",
+ "extra": "mean: 32.86536988123778 usec\nrounds: 14164"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary",
+ "value": 32288.153137201123,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0000021872234414808735",
+ "extra": "mean: 30.97111178055706 usec\nrounds: 15101"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml_deep",
+ "value": 284.3052779648135,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00002119795391927093",
+ "extra": "mean: 3.5173458866414817 msec\nrounds: 247"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml_wide",
+ "value": 0.7247622618050542,
+ "unit": "iter/sec",
+ "range": "stddev: 0.016197633655692253",
+ "extra": "mean: 1.3797627894000073 sec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation_deep",
+ "value": 361.24198902906744,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000053709243070328815",
+ "extra": "mean: 2.768227477342161 msec\nrounds: 331"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation_wide",
+ "value": 0.9209113636788201,
+ "unit": "iter/sec",
+ "range": "stddev: 0.006243087274787177",
+ "extra": "mean: 1.085880834400001 sec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation_wide_array",
+ "value": 1.5534795298378319,
+ "unit": "iter/sec",
+ "range": "stddev: 0.004737098711267636",
+ "extra": "mean: 643.716238799999 msec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary_deep",
+ "value": 310.5755518782681,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00002613502073306418",
+ "extra": "mean: 3.219828457044668 msec\nrounds: 291"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary_wide",
+ "value": 0.8077209945185349,
+ "unit": "iter/sec",
+ "range": "stddev: 0.01187644725045888",
+ "extra": "mean: 1.2380512662000058 sec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary_wide_array",
+ "value": 1.080027477964048,
+ "unit": "iter/sec",
+ "range": "stddev: 0.001494319381775762",
+ "extra": "mean: 925.9023686000035 msec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_parse_xml_deep",
+ "value": 356.75666209532955,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0037188877925861496",
+ "extra": "mean: 2.803031046783335 msec\nrounds: 342"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_deep",
+ "value": 255.45211473630428,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00004148517106775961",
+ "extra": "mean: 3.914627996062083 msec\nrounds: 254"
+ }
+ ]
+ },
+ {
+ "commit": {
+ "author": {
+ "email": "nat@lindenlab.com",
+ "name": "nat-goodspeed",
+ "username": "nat-goodspeed"
+ },
+ "committer": {
+ "email": "noreply@github.com",
+ "name": "GitHub",
+ "username": "web-flow"
+ },
+ "distinct": true,
+ "id": "5b63d1cd920b7467b1923fbe655e2bfd649bdf89",
+ "message": "Merge pull request #20 from secondlife/dependabot/github_actions/actions/upload-artifact-4\n\nBump actions/upload-artifact from 3 to 4",
+ "timestamp": "2024-01-02T17:04:54-05:00",
+ "tree_id": "6bedc0fbf3e18822694ca41b607b30d3739af50a",
+ "url": "https://github.com/secondlife/python-llsd/commit/5b63d1cd920b7467b1923fbe655e2bfd649bdf89"
+ },
+ "date": 1704233173729,
+ "tool": "pytest",
+ "benches": [
+ {
+ "name": "tests/bench.py::test_parse_xml_stream",
+ "value": 15769.089493607331,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000003844633524595741",
+ "extra": "mean: 63.41520227945896 usec\nrounds: 5616"
+ },
+ {
+ "name": "tests/bench.py::test_parse_notation_stream",
+ "value": 5339.77006960269,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00002338108387787813",
+ "extra": "mean: 187.27398126983508 usec\nrounds: 3684"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_stream",
+ "value": 19235.995523144546,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000027955748351179218",
+ "extra": "mean: 51.98587194495916 usec\nrounds: 8020"
+ },
+ {
+ "name": "tests/bench.py::test_parse_notation_bytes",
+ "value": 5746.025245985933,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000025343188618617877",
+ "extra": "mean: 174.03334604187157 usec\nrounds: 4800"
+ },
+ {
+ "name": "tests/bench.py::test_parse_xml_bytes",
+ "value": 19347.75999133648,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000002971922739142828",
+ "extra": "mean: 51.68556982553944 usec\nrounds: 4010"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_bytes",
+ "value": 21285.335754157324,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000029437407713210442",
+ "extra": "mean: 46.98070124661698 usec\nrounds: 16927"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml",
+ "value": 25531.57909239875,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000010580367957196139",
+ "extra": "mean: 39.16718180183847 usec\nrounds: 11573"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation",
+ "value": 30416.006564151143,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000009935038166048219",
+ "extra": "mean: 32.877425834679364 usec\nrounds: 14043"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary",
+ "value": 32054.371901507402,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0000026487228024801767",
+ "extra": "mean: 31.196992506129046 usec\nrounds: 14546"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml_deep",
+ "value": 285.6737382535751,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00003629488954449132",
+ "extra": "mean: 3.5004967768943507 msec\nrounds: 251"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml_wide",
+ "value": 0.7402543352994372,
+ "unit": "iter/sec",
+ "range": "stddev: 0.014458880435002406",
+ "extra": "mean: 1.3508870564000062 sec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation_deep",
+ "value": 369.97786979043366,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00009672905832438023",
+ "extra": "mean: 2.70286436474276 msec\nrounds: 329"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation_wide",
+ "value": 0.9329679625787793,
+ "unit": "iter/sec",
+ "range": "stddev: 0.011084448751030202",
+ "extra": "mean: 1.071848166399991 sec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation_wide_array",
+ "value": 1.5406054815501788,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00297824455968108",
+ "extra": "mean: 649.0954445999932 msec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary_deep",
+ "value": 314.42037649064304,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00003219010147908321",
+ "extra": "mean: 3.1804554499977185 msec\nrounds: 300"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary_wide",
+ "value": 0.8083644073987081,
+ "unit": "iter/sec",
+ "range": "stddev: 0.022438961657121583",
+ "extra": "mean: 1.2370658466000122 sec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary_wide_array",
+ "value": 1.0711350563990751,
+ "unit": "iter/sec",
+ "range": "stddev: 0.008000223907686208",
+ "extra": "mean: 933.5890876000121 msec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_parse_xml_deep",
+ "value": 308.31658465320214,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00649825421827752",
+ "extra": "mean: 3.2434194259280957 msec\nrounds: 324"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_deep",
+ "value": 259.7446542997554,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00005898358736048852",
+ "extra": "mean: 3.849934862743937 msec\nrounds: 255"
+ }
+ ]
+ },
+ {
+ "commit": {
+ "author": {
+ "email": "signal@lindenlab.com",
+ "name": "Signal Linden",
+ "username": "bennettgoble"
+ },
+ "committer": {
+ "email": "noreply@github.com",
+ "name": "GitHub",
+ "username": "web-flow"
+ },
+ "distinct": true,
+ "id": "c806ece709dc7327f54e12cd0a85746b734bec4a",
+ "message": "Merge pull request #22 from secondlife/signal/codecov\n\nBump codecov-action to v4",
+ "timestamp": "2024-02-01T08:48:42-08:00",
+ "tree_id": "c78813db2067ffe9dc2b99a1a098ae8a7a7dde1b",
+ "url": "https://github.com/secondlife/python-llsd/commit/c806ece709dc7327f54e12cd0a85746b734bec4a"
+ },
+ "date": 1706806195146,
+ "tool": "pytest",
+ "benches": [
+ {
+ "name": "tests/bench.py::test_parse_xml_stream",
+ "value": 15347.358820702611,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000005450338281102883",
+ "extra": "mean: 65.15779110155836 usec\nrounds: 4203"
+ },
+ {
+ "name": "tests/bench.py::test_parse_notation_stream",
+ "value": 5288.741300860378,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000023388532612794963",
+ "extra": "mean: 189.08090661143115 usec\nrounds: 3373"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_stream",
+ "value": 19293.6063103556,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000027867923674971253",
+ "extra": "mean: 51.830641919093296 usec\nrounds: 11193"
+ },
+ {
+ "name": "tests/bench.py::test_parse_notation_bytes",
+ "value": 5651.18047323247,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000025264927663956554",
+ "extra": "mean: 176.9541788192089 usec\nrounds: 4032"
+ },
+ {
+ "name": "tests/bench.py::test_parse_xml_bytes",
+ "value": 19154.890757567064,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0000030005141038747245",
+ "extra": "mean: 52.20598815500704 usec\nrounds: 3799"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_bytes",
+ "value": 21184.636765771902,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000030012256734448774",
+ "extra": "mean: 47.204019169953575 usec\nrounds: 12624"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml",
+ "value": 24718.948616065412,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000010599726805374958",
+ "extra": "mean: 40.45479504537167 usec\nrounds: 9607"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation",
+ "value": 30007.52430801591,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000010159379950217543",
+ "extra": "mean: 33.324975087427326 usec\nrounds: 15133"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary",
+ "value": 31920.89511089033,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000001827018336480383",
+ "extra": "mean: 31.32744230780777 usec\nrounds: 13364"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml_deep",
+ "value": 285.4940421694391,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00026207913101627413",
+ "extra": "mean: 3.502700064775802 msec\nrounds: 247"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml_wide",
+ "value": 0.7378949977398735,
+ "unit": "iter/sec",
+ "range": "stddev: 0.006005235618657384",
+ "extra": "mean: 1.3552063681999982 sec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation_deep",
+ "value": 354.63107863916923,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00005461366296289827",
+ "extra": "mean: 2.8198318202604065 msec\nrounds: 306"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation_wide",
+ "value": 0.9081130541100204,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0023691583071882875",
+ "extra": "mean: 1.101184478600004 sec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation_wide_array",
+ "value": 1.5445717578790732,
+ "unit": "iter/sec",
+ "range": "stddev: 0.004919848933425914",
+ "extra": "mean: 647.4286447999987 msec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary_deep",
+ "value": 307.5966753600674,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000017726619914937687",
+ "extra": "mean: 3.2510104305562373 msec\nrounds: 288"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary_wide",
+ "value": 0.7960918793705465,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0059001806846304666",
+ "extra": "mean: 1.2561364157999946 sec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary_wide_array",
+ "value": 1.1138691084497798,
+ "unit": "iter/sec",
+ "range": "stddev: 0.01276072662246532",
+ "extra": "mean: 897.7715535999948 msec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_parse_xml_deep",
+ "value": 353.0252910370794,
+ "unit": "iter/sec",
+ "range": "stddev: 0.003966884895120551",
+ "extra": "mean: 2.83265824117674 msec\nrounds: 340"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_deep",
+ "value": 253.97927621589147,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000036906851917373934",
+ "extra": "mean: 3.937329119522194 msec\nrounds: 251"
+ }
+ ]
+ },
+ {
+ "commit": {
+ "author": {
+ "email": "signal@lindenlab.com",
+ "name": "Signal Linden",
+ "username": "bennettgoble"
+ },
+ "committer": {
+ "email": "noreply@github.com",
+ "name": "GitHub",
+ "username": "web-flow"
+ },
+ "distinct": true,
+ "id": "acb55e3d613f131371d4a470f772f0e322f4bcce",
+ "message": "Merge pull request #23 from secondlife/signal/fix-array-indent\n\nFix array indentation of pretty xml",
+ "timestamp": "2024-04-01T23:35:52-07:00",
+ "tree_id": "bd5010d3fc8eb79caa56e9d25cdcf456ee4b3bc1",
+ "url": "https://github.com/secondlife/python-llsd/commit/acb55e3d613f131371d4a470f772f0e322f4bcce"
+ },
+ "date": 1712039822653,
+ "tool": "pytest",
+ "benches": [
+ {
+ "name": "tests/bench.py::test_parse_xml_stream",
+ "value": 15338.036976363388,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000004331856709993063",
+ "extra": "mean: 65.19739139637265 usec\nrounds: 4254"
+ },
+ {
+ "name": "tests/bench.py::test_parse_notation_stream",
+ "value": 5332.396264314848,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0000245948764983066",
+ "extra": "mean: 187.53294962194425 usec\nrounds: 3176"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_stream",
+ "value": 19284.815864952467,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000027818135030237138",
+ "extra": "mean: 51.854267471506645 usec\nrounds: 10188"
+ },
+ {
+ "name": "tests/bench.py::test_parse_notation_bytes",
+ "value": 5854.368214946115,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000025867648343098357",
+ "extra": "mean: 170.81262457100237 usec\nrounds: 4371"
+ },
+ {
+ "name": "tests/bench.py::test_parse_xml_bytes",
+ "value": 19263.501614767185,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000005072631884570145",
+ "extra": "mean: 51.9116420263599 usec\nrounds: 9199"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_bytes",
+ "value": 21464.343697156215,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000029175897140904308",
+ "extra": "mean: 46.588892449224474 usec\nrounds: 12078"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml",
+ "value": 24926.216480845855,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00001046848390926289",
+ "extra": "mean: 40.118403078478984 usec\nrounds: 10720"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation",
+ "value": 29926.614027771157,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000011045711956936568",
+ "extra": "mean: 33.41507325459622 usec\nrounds: 13651"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary",
+ "value": 31497.118948059262,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000001664586674172829",
+ "extra": "mean: 31.74893556610886 usec\nrounds: 10988"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml_deep",
+ "value": 285.4127173566864,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000039951208860490064",
+ "extra": "mean: 3.5036981157019658 msec\nrounds: 242"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml_wide",
+ "value": 0.7331961327654465,
+ "unit": "iter/sec",
+ "range": "stddev: 0.004417990449218888",
+ "extra": "mean: 1.3638915363999957 sec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation_deep",
+ "value": 356.5444582953051,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00011026263356797399",
+ "extra": "mean: 2.804699320755556 msec\nrounds: 318"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation_wide",
+ "value": 0.9236691727590265,
+ "unit": "iter/sec",
+ "range": "stddev: 0.007131136617704611",
+ "extra": "mean: 1.0826387082000053 sec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation_wide_array",
+ "value": 1.5434002125635595,
+ "unit": "iter/sec",
+ "range": "stddev: 0.010704752604469039",
+ "extra": "mean: 647.920087 msec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary_deep",
+ "value": 297.09737409990527,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00003245059419092853",
+ "extra": "mean: 3.3658998267138127 msec\nrounds: 277"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary_wide",
+ "value": 0.7493606807246287,
+ "unit": "iter/sec",
+ "range": "stddev: 0.004469532851903014",
+ "extra": "mean: 1.3344708705999948 sec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary_wide_array",
+ "value": 1.0724915981351262,
+ "unit": "iter/sec",
+ "range": "stddev: 0.005393651071731648",
+ "extra": "mean: 932.408236800012 msec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_parse_xml_deep",
+ "value": 332.52609466548023,
+ "unit": "iter/sec",
+ "range": "stddev: 0.005866860812937119",
+ "extra": "mean: 3.007282784847293 msec\nrounds: 330"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_deep",
+ "value": 252.77433834590374,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00011968375288348899",
+ "extra": "mean: 3.956097784861258 msec\nrounds: 251"
+ }
+ ]
+ },
+ {
+ "commit": {
+ "author": {
+ "email": "signal@lindenlab.com",
+ "name": "Signal Linden",
+ "username": "bennettgoble"
+ },
+ "committer": {
+ "email": "noreply@github.com",
+ "name": "GitHub",
+ "username": "web-flow"
+ },
+ "distinct": true,
+ "id": "ee53c4c4c2af234b5e65c3cbf2a99ad852c6919d",
+ "message": "Merge pull request #24 from secondlife/nattylinden/pre-commit\n\nUpdate pre-commit hooks to avoid isort installation error",
+ "timestamp": "2024-07-24T08:24:37-07:00",
+ "tree_id": "4ee9147f3339f0dc142462876d8cc37a146f949b",
+ "url": "https://github.com/secondlife/python-llsd/commit/ee53c4c4c2af234b5e65c3cbf2a99ad852c6919d"
+ },
+ "date": 1721834748098,
+ "tool": "pytest",
+ "benches": [
+ {
+ "name": "tests/bench.py::test_parse_xml_stream",
+ "value": 15660.262442643065,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000003548137417958026",
+ "extra": "mean: 63.85589026126338 usec\nrounds: 4210"
+ },
+ {
+ "name": "tests/bench.py::test_parse_notation_stream",
+ "value": 5389.110365094642,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00002627231306259801",
+ "extra": "mean: 185.5593840640223 usec\nrounds: 3627"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_stream",
+ "value": 19552.914686100867,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000029079022158787694",
+ "extra": "mean: 51.14327025171583 usec\nrounds: 11530"
+ },
+ {
+ "name": "tests/bench.py::test_parse_notation_bytes",
+ "value": 5853.644424330927,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000028775779240083275",
+ "extra": "mean: 170.8337451867518 usec\nrounds: 4415"
+ },
+ {
+ "name": "tests/bench.py::test_parse_xml_bytes",
+ "value": 19343.018241922593,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000002707553436047833",
+ "extra": "mean: 51.69824003126232 usec\nrounds: 8978"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_bytes",
+ "value": 21605.719305060265,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000030575954842135505",
+ "extra": "mean: 46.284041085630065 usec\nrounds: 13046"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml",
+ "value": 25084.271280482706,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000011414889962911467",
+ "extra": "mean: 39.86561892982193 usec\nrounds: 10111"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation",
+ "value": 30488.6213954444,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000010598975323594875",
+ "extra": "mean: 32.7991215814507 usec\nrounds: 14114"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary",
+ "value": 31890.08024579081,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0000016020151060664976",
+ "extra": "mean: 31.35771350503235 usec\nrounds: 13906"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml_deep",
+ "value": 287.9811060890427,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00008228945465947704",
+ "extra": "mean: 3.4724500283390243 msec\nrounds: 247"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml_wide",
+ "value": 0.7290009188003955,
+ "unit": "iter/sec",
+ "range": "stddev: 0.012525721075285342",
+ "extra": "mean: 1.3717403835999904 sec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation_deep",
+ "value": 359.88609614065064,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00007283429156779202",
+ "extra": "mean: 2.7786569437491693 msec\nrounds: 320"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation_wide",
+ "value": 0.9191501363127588,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0054037221755862015",
+ "extra": "mean: 1.0879615424000009 sec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation_wide_array",
+ "value": 1.5688287384750186,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0018886439807905661",
+ "extra": "mean: 637.4182060000066 msec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary_deep",
+ "value": 304.9049846786711,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00011654443619683",
+ "extra": "mean: 3.2797102384333456 msec\nrounds: 281"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary_wide",
+ "value": 0.7721258429625174,
+ "unit": "iter/sec",
+ "range": "stddev: 0.025859205345833917",
+ "extra": "mean: 1.2951256704000058 sec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary_wide_array",
+ "value": 1.096124343954483,
+ "unit": "iter/sec",
+ "range": "stddev: 0.014240544140814227",
+ "extra": "mean: 912.3052557999983 msec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_parse_xml_deep",
+ "value": 354.3760545909131,
+ "unit": "iter/sec",
+ "range": "stddev: 0.004031652751633972",
+ "extra": "mean: 2.8218610909091653 msec\nrounds: 330"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_deep",
+ "value": 261.7145531245397,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00008492952548364103",
+ "extra": "mean: 3.8209567945735876 msec\nrounds: 258"
+ }
+ ]
+ },
+ {
+ "commit": {
+ "author": {
+ "email": "signal@lindenlab.com",
+ "name": "Signal Linden",
+ "username": "bennettgoble"
+ },
+ "committer": {
+ "email": "noreply@github.com",
+ "name": "GitHub",
+ "username": "web-flow"
+ },
+ "distinct": true,
+ "id": "1a5ce3e8161422a5eb25df15f6b7817792c789ba",
+ "message": "Merge pull request #25 from secondlife/dependabot/github_actions/codecov/codecov-action-5\n\nBump codecov/codecov-action from 4 to 5",
+ "timestamp": "2025-03-15T09:31:29-07:00",
+ "tree_id": "ec5213c2c2e6a731dd5be9305a108f634c3b7f86",
+ "url": "https://github.com/secondlife/python-llsd/commit/1a5ce3e8161422a5eb25df15f6b7817792c789ba"
+ },
+ "date": 1742056357497,
+ "tool": "pytest",
+ "benches": [
+ {
+ "name": "tests/bench.py::test_parse_xml_stream",
+ "value": 15606.945919497297,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00000506948781494805",
+ "extra": "mean: 64.07403505837293 usec\nrounds: 5334"
+ },
+ {
+ "name": "tests/bench.py::test_parse_notation_stream",
+ "value": 5224.591737187256,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00002452157777505783",
+ "extra": "mean: 191.4025153166066 usec\nrounds: 3297"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_stream",
+ "value": 19254.738851288545,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000028661407461321518",
+ "extra": "mean: 51.93526683084975 usec\nrounds: 10977"
+ },
+ {
+ "name": "tests/bench.py::test_parse_notation_bytes",
+ "value": 5653.205286006255,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000025768814437985244",
+ "extra": "mean: 176.89079900837223 usec\nrounds: 4841"
+ },
+ {
+ "name": "tests/bench.py::test_parse_xml_bytes",
+ "value": 19804.97420317452,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0000036738295406410742",
+ "extra": "mean: 50.49236569264054 usec\nrounds: 9992"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_bytes",
+ "value": 21143.99495727199,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000030447738622913495",
+ "extra": "mean: 47.29475210435921 usec\nrounds: 15087"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml",
+ "value": 24401.255972155745,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000010862009887744549",
+ "extra": "mean: 40.9814970647863 usec\nrounds: 9880"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation",
+ "value": 30142.561881501522,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000010583096775969268",
+ "extra": "mean: 33.17568041931099 usec\nrounds: 14785"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary",
+ "value": 31873.289181523698,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000003014995156978838",
+ "extra": "mean: 31.374232960546784 usec\nrounds: 11092"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml_deep",
+ "value": 275.2747944623416,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000029096590493651033",
+ "extra": "mean: 3.6327336178859735 msec\nrounds: 246"
+ },
+ {
+ "name": "tests/bench.py::test_format_xml_wide",
+ "value": 0.7101375556229714,
+ "unit": "iter/sec",
+ "range": "stddev: 0.01350042453332921",
+ "extra": "mean: 1.408177883399992 sec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation_deep",
+ "value": 348.896057338846,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00012521640913727234",
+ "extra": "mean: 2.8661831481483477 msec\nrounds: 324"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation_wide",
+ "value": 0.8996757730095942,
+ "unit": "iter/sec",
+ "range": "stddev: 0.008334080178187877",
+ "extra": "mean: 1.1115115355999876 sec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_notation_wide_array",
+ "value": 1.5374093643485627,
+ "unit": "iter/sec",
+ "range": "stddev: 0.0011989562830601419",
+ "extra": "mean: 650.4448478000029 msec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary_deep",
+ "value": 309.6512729152026,
+ "unit": "iter/sec",
+ "range": "stddev: 0.000019654658458515325",
+ "extra": "mean: 3.22943933214138 msec\nrounds: 280"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary_wide",
+ "value": 0.7835275338398409,
+ "unit": "iter/sec",
+ "range": "stddev: 0.019479325711172318",
+ "extra": "mean: 1.2762793351999904 sec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_format_binary_wide_array",
+ "value": 1.101996216578525,
+ "unit": "iter/sec",
+ "range": "stddev: 0.017138832226022648",
+ "extra": "mean: 907.444131800014 msec\nrounds: 5"
+ },
+ {
+ "name": "tests/bench.py::test_parse_xml_deep",
+ "value": 310.9819956175169,
+ "unit": "iter/sec",
+ "range": "stddev: 0.006865779858470243",
+ "extra": "mean: 3.215620241983142 msec\nrounds: 343"
+ },
+ {
+ "name": "tests/bench.py::test_parse_binary_deep",
+ "value": 258.31266590151614,
+ "unit": "iter/sec",
+ "range": "stddev: 0.00003206944259462411",
+ "extra": "mean: 3.8712774555981637 msec\nrounds: 259"
+ }
+ ]
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/dev/bench/index.html b/dev/bench/index.html
new file mode 100644
index 0000000..6c88780
--- /dev/null
+++ b/dev/bench/index.html
@@ -0,0 +1,281 @@
+
+
+
+
+
+
+ Codestin Search App
+
+
+
+
+
+
+ Download data as JSON
+
+
+
+
+
+
+
+
+
diff --git a/llsd/__init__.py b/llsd/__init__.py
deleted file mode 100644
index f746ca2..0000000
--- a/llsd/__init__.py
+++ /dev/null
@@ -1,81 +0,0 @@
-"""
-Types as well as parsing and formatting functions for handling LLSD.
-
-This is the llsd module -- parsers and formatters between the
-supported subset of mime types and python objects. Documentation
-available on the Second Life wiki:
-
-http://wiki.secondlife.com/wiki/LLSD
-"""
-from llsd.base import (_LLSD, BINARY_MIME_TYPE, NOTATION_MIME_TYPE, XML_MIME_TYPE,
- BINARY_HEADER, NOTATION_HEADER, XML_HEADER,
- LLSDBaseParser, LLSDParseError, LLSDSerializationError,
- LongType, UnicodeType, binary, undef, uri)
-from llsd.serde_binary import (LLSDBinaryParser, format_binary, parse_binary, parse_binary_nohdr,
- write_binary)
-from llsd.serde_notation import (LLSDNotationFormatter, write_notation, format_notation,
- LLSDNotationParser, parse_notation, parse_notation_nohdr)
-from llsd.serde_xml import (LLSDXMLFormatter, LLSDXMLPrettyFormatter,
- write_pretty_xml, write_xml, format_pretty_xml, format_xml,
- parse_xml, parse_xml_nohdr)
-
-
-def parse(something, mime_type = None):
- """
- This is the basic public interface for parsing llsd.
-
- :param something: The data to parse. This is expected to be bytes, not
- strings, or a byte stream.
- :param mime_type: The mime_type of the data if it is known.
- :returns: Returns a python object.
-
- Python 3 Note: when reading LLSD from a file, use open()'s 'rb' mode explicitly
- """
- try:
- if mime_type:
- # explicit mime_type -- 'something' may or may not also have a header
- for mime_types, parser in (
- ({XML_MIME_TYPE, 'application/llsd'}, parse_xml),
- ({BINARY_MIME_TYPE}, parse_binary),
- ({NOTATION_MIME_TYPE}, parse_notation),
-## ({'application/json'}, parse_notation),
- ):
- if mime_type.lower() in mime_types:
- return parser(something)
-
- # no recognized mime type, look for header
- baseparser = LLSDBaseParser(something)
- for pattern, parser in (
- (BINARY_HEADER, parse_binary_nohdr),
- (NOTATION_HEADER, parse_notation_nohdr),
- (XML_HEADER, parse_xml_nohdr),
- ):
- if baseparser.matchseq(pattern):
- # we already saw the header, don't check again
- return parser(baseparser)
-
- # no recognized header -- does content resemble XML?
- if baseparser.starts_with(b'<'):
- return parse_xml_nohdr(baseparser)
- else:
- return parse_notation_nohdr(baseparser)
-
- except KeyError as e:
- raise LLSDParseError('LLSD could not be parsed: %s' % (e,))
- except TypeError as e:
- raise LLSDParseError('Input stream not of type bytes. %s' % (e,))
-
-
-class LLSD(_LLSD):
- def __bytes__(self):
- return self.as_xml(self.thing)
-
-
- def __str__(self):
- return self.__bytes__().decode()
-
- parse = staticmethod(parse)
- as_xml = staticmethod(format_xml)
- as_pretty_xml = staticmethod(format_pretty_xml)
- as_binary = staticmethod(format_binary)
- as_notation = staticmethod(format_notation)
diff --git a/llsd/base.py b/llsd/base.py
deleted file mode 100644
index e7204ca..0000000
--- a/llsd/base.py
+++ /dev/null
@@ -1,582 +0,0 @@
-import abc
-import base64
-import binascii
-import datetime
-import io
-import os
-import re
-import sys
-import types
-import uuid
-
-try:
- # If the future package is installed, then we support it. Any clients in
- # python 2 using its str builtin replacement will actually be using instances
- # of newstr, so we need to properly detect that as a string type
- # for details see the docs: http://python-future.org/str_object.html
- from future.types.newstr import newstr
-except ImportError:
- # otherwise we pass over it in silence
- newstr = str
-
-PY2 = sys.version_info[0] == 2
-
-XML_MIME_TYPE = 'application/llsd+xml'
-BINARY_MIME_TYPE = 'application/llsd+binary'
-NOTATION_MIME_TYPE = 'application/llsd+notation'
-
-XML_HEADER = b' llsd/xml ?>'
-BINARY_HEADER = b' llsd/binary ?>'
-NOTATION_HEADER = b' llsd/notation ?>'
-
-ALL_CHARS = str(bytearray(range(256))) if PY2 else bytes(range(256))
-
-MAX_FORMAT_DEPTH = 200
-MAX_PARSE_DEPTH = 200
-
-class _LLSD:
- __metaclass__ = abc.ABCMeta
-
- def __init__(self, thing=None):
- self.thing = thing
-
-
-undef = _LLSD(None)
-
-
-# 'binary' only exists so that a Python 2 caller can distinguish binary data
-# from str data - since in Python 2, (bytes is str).
-if PY2:
- class binary(str):
- "Simple wrapper for llsd.binary data."
- pass
-else:
- binary = bytes
-
-
-class uri(str):
- "Simple wrapper for llsd.uri data."
- pass
-
-
-class LLSDParseError(Exception):
- "Exception raised when the parser fails."
- pass
-
-
-class LLSDSerializationError(TypeError):
- "Exception raised when serialization fails."
- pass
-
-
-# In Python 2, this expression produces (str, unicode); in Python 3 it's
-# simply (str,). Either way, it's valid to test isinstance(somevar,
-# StringTypes). (Some consumers test (type(somevar) in StringTypes), so we do
-# want (str,) rather than plain str.)
-StringTypes = tuple(set((type(''), type(u''), newstr)))
-
-try:
- LongType = long
- IntTypes = (int, long)
-except NameError:
- LongType = int
- IntTypes = int
-
-try:
- UnicodeType = unicode
-except NameError:
- UnicodeType = str
-
-try:
- b'%s' % (b'yes',)
-except TypeError:
- # There's a range of Python 3 versions, up through Python 3.4, for which
- # bytes interpolation (bytes value with % operator) does not work. This
- # hack can be removed once we no longer care about Python 3.4 -- in other
- # words, once we're beyond jessie everywhere.
- class B(object):
- """
- Instead of writing:
- b'format string' % stuff
- write:
- B('format string') % stuff
- This class performs the conversions necessary to support bytes
- interpolation when the language doesn't natively support it.
- (We considered naming this class b, but that would be too confusing.)
- """
- def __init__(self, fmt):
- # Instead of storing the format string as bytes and converting it
- # to string every time, convert initially and store the string.
- try:
- self.strfmt = fmt.decode('utf-8')
- except AttributeError:
- # caller passed a string literal rather than a bytes literal
- self.strfmt = fmt
-
- def __mod__(self, args):
- # __mod__() is engaged for (self % args)
- if not isinstance(args, tuple):
- # Unify the tuple and non-tuple cases.
- args = (args,)
- # In principle, this is simple: convert everything to string,
- # interpolate, convert back. It's complicated by the fact that we
- # must handle non-bytes args.
- strargs = []
- for arg in args:
- try:
- decoder = arg.decode
- except AttributeError:
- # use arg exactly as is
- strargs.append(arg)
- else:
- # convert from bytes to string
- strargs.append(decoder('utf-8'))
- return (self.strfmt % tuple(strargs)).encode('utf-8')
-else:
- # bytes interpolation Just Works
- def B(fmt):
- try:
- # In the usual case, caller wrote B('fmt') rather than b'fmt'. But
- # s/he really wants a bytes literal here. Encode the passed string.
- return fmt.encode('utf-8')
- except AttributeError:
- # Caller wrote B(b'fmt')?
- return fmt
-
-
-def is_integer(o):
- """ portable test if an object is like an int """
- return isinstance(o, IntTypes)
-
-
-def is_unicode(o):
- """ portable check if an object is unicode and not bytes """
- return isinstance(o, UnicodeType)
-
-
-def is_string(o):
- """ portable check if an object is string-like """
- return isinstance(o, StringTypes)
-
-
-#date: d"YYYY-MM-DDTHH:MM:SS.FFFFFFZ"
-_date_regex = re.compile(r"(?P\d{4})-(?P\d{2})-(?P\d{2})T"
- r"(?P\d{2}):(?P\d{2}):(?P\d{2})"
- r"(?P(\.\d+)?)Z")
-
-
-def _str_to_bytes(s):
- if is_unicode(s):
- return s.encode('utf-8')
- else:
- return s
-
-
-def _format_datestr(v):
- """
- Formats a datetime or date object into the string format shared by
- xml and notation serializations.
- """
- if not isinstance(v, datetime.date) and not isinstance(v, datetime.datetime):
- raise LLSDSerializationError("invalid date string %s passed to date formatter" % v)
-
- if not isinstance(v, datetime.datetime):
- v = datetime.datetime.combine(v, datetime.time(0))
-
- return _str_to_bytes(v.isoformat() + 'Z')
-
-
-def _parse_datestr(datestr):
- """
- Parses a datetime object from the string format shared by
- xml and notation serializations.
- """
- if datestr == "":
- return datetime.datetime(1970, 1, 1)
-
- match = re.match(_date_regex, datestr)
- if not match:
- raise LLSDParseError("invalid date string '%s'." % datestr)
-
- year = int(match.group('year'))
- month = int(match.group('month'))
- day = int(match.group('day'))
- hour = int(match.group('hour'))
- minute = int(match.group('minute'))
- second = int(match.group('second'))
- seconds_float = match.group('second_float')
- usec = 0
- if seconds_float:
- usec = int(float('0' + seconds_float) * 1e6)
- return datetime.datetime(year, month, day, hour, minute, second, usec)
-
-
-def _bool_to_python(node, depth=0):
- "Convert boolean node to a python object."
- val = node.text or ''
- try:
- # string value, accept 'true' or 'True' or whatever
- return (val.lower() in ('true', '1', '1.0'))
- except AttributeError:
- # not a string (no lower() method), use normal Python rules
- return bool(val)
-
-
-def _int_to_python(node, depth=0):
- "Convert integer node to a python object."
- val = node.text or ''
- if not val.strip():
- return 0
- return int(val)
-
-
-def _real_to_python(node, depth=0):
- "Convert floating point node to a python object."
- val = node.text or ''
- if not val.strip():
- return 0.0
- return float(val)
-
-
-def _uuid_to_python(node, depth=0):
- "Convert uuid node to a python object."
- if node.text:
- return uuid.UUID(hex=node.text)
- return uuid.UUID(int=0)
-
-
-def _str_to_python(node, depth=0):
- "Convert string node to a python object."
- return node.text or ''
-
-
-def _bin_to_python(node, depth=0):
- base = node.get('encoding') or 'base64'
- try:
- if base == 'base16':
- # parse base16 encoded data
- return binary(base64.b16decode(node.text or ''))
- elif base == 'base64':
- # parse base64 encoded data
- return binary(base64.b64decode(node.text or ''))
- elif base == 'base85':
- return LLSDParseError("Parser doesn't support base85 encoding")
- except binascii.Error as exc:
- # convert exception class so it's more catchable
- return LLSDParseError("Encoded binary data: " + str(exc))
- except TypeError as exc:
- # convert exception class so it's more catchable
- return LLSDParseError("Bad binary data: " + str(exc))
-
-
-def _date_to_python(node, depth=0):
- "Convert date node to a python object."
- val = node.text or ''
- if not val:
- val = "1970-01-01T00:00:00Z"
- return _parse_datestr(val)
-
-
-def _uri_to_python(node, depth=0):
- "Convert uri node to a python object."
- val = node.text or ''
- return uri(val)
-
-
-def _map_to_python(node, depth=0):
- "Convert map node to a python object."
- result = {}
- for index in range(len(node))[::2]:
- if node[index].text is None:
- result[''] = _to_python(node[index+1], depth+1)
- else:
- result[node[index].text] = _to_python(node[index+1], depth+1)
- return result
-
-
-def _array_to_python(node, depth=0):
- "Convert array node to a python object."
- return [_to_python(child, depth+1) for child in node]
-
-
-NODE_HANDLERS = dict(
- undef=lambda x,y: None,
- boolean=_bool_to_python,
- integer=_int_to_python,
- real=_real_to_python,
- uuid=_uuid_to_python,
- string=_str_to_python,
- binary=_bin_to_python,
- date=_date_to_python,
- uri=_uri_to_python,
- map=_map_to_python,
- array=_array_to_python,
-)
-
-
-def _to_python(node, depth=0):
- "Convert node to a python object."
- if depth > MAX_PARSE_DEPTH:
- raise LLSDParseError("Cannot parse depth of more than %d" % MAX_PARSE_DEPTH)
-
- return NODE_HANDLERS[node.tag](node, depth)
-
-
-class LLSDBaseFormatter(object):
- """
- This base class cannot be instantiated on its own: it assumes a subclass
- containing methods with canonical names specified in self.__init__(). The
- role of this base class is to provide self.type_map based on the methods
- defined in its subclass.
- """
- __slots__ = ['stream', 'type_map']
-
- def __init__(self):
- "Construct a new formatter dispatch table."
- self.stream = None
- self.type_map = {
- type(None): self._UNDEF,
- undef: self._UNDEF,
- bool: self._BOOLEAN,
- int: self._INTEGER,
- LongType: self._INTEGER,
- float: self._REAL,
- uuid.UUID: self._UUID,
- binary: self._BINARY,
- str: self._STRING,
- UnicodeType: self._STRING,
- newstr: self._STRING,
- uri: self._URI,
- datetime.datetime: self._DATE,
- datetime.date: self._DATE,
- list: self._ARRAY,
- tuple: self._ARRAY,
- types.GeneratorType: self._ARRAY,
- dict: self._MAP,
- _LLSD: self._LLSD,
- }
-
-
- def format(self, something):
- """
- Pure Python implementation of the formatter.
- Format a python object according to subclass formatting.
-
- :param something: A python object (typically a dict) to be serialized.
- :returns: A serialized bytes object.
- """
- stream = io.BytesIO()
- self.write(stream, something)
- return stream.getvalue()
-
- def write(self, stream, something):
- """
- Serialize a python object to the passed binary 'stream' according to
- subclass formatting.
-
- :param stream: A binary file-like object to which to serialize 'something'.
- :param something: A python object (typically a dict) to be serialized.
- """
- self.stream = stream
- try:
- return self._write(something)
- finally:
- self.stream = None
-
-
-_X_ORD = ord(b'x')
-_BACKSLASH_ORD = ord(b'\\')
-_DECODE_BUFF_ALLOC_SIZE = 1024
-
-
-class LLSDBaseParser(object):
- """
- Utility methods useful for parser subclasses.
- """
- __slots__ = ['_stream', '_decode_buff']
-
- def __init__(self, something=b''):
- self._reset(something)
- # Scratch space for decoding delimited strings
- self._decode_buff = bytearray(_DECODE_BUFF_ALLOC_SIZE)
-
- def _reset(self, something):
- if isinstance(something, LLSDBaseParser):
- # When passed an existing LLSDBaseParser (subclass) instance, just
- # borrow its existing _stream.
- self._stream = something._stream
- elif isinstance(something, bytes):
- # Wrap an incoming bytes string into a stream. If the passed bytes
- # string is so large that the overhead of copying it into a
- # BytesIO is significant, advise caller to pass a stream instead.
- self._stream = io.BytesIO(something)
- elif something.seekable():
- # 'something' is already a seekable stream, use directly
- self._stream = something
- else:
- # 'something' isn't seekable, wrap in BufferedReader
- # (let BufferedReader handle the problem of passing an
- # inappropriate object)
- self._stream = io.BufferedReader(something)
-
- def starts_with(self, pattern):
- """
- Like matchseq(), except that starts_with() doesn't consume what it
- matches: it always resets our input stream to its previous position.
- """
- oldpos = self._stream.tell()
- try:
- return self.matchseq(pattern)
- finally:
- self._stream.seek(oldpos)
-
- def matchseq(self, pattern):
- """
- Match bytes object 'pattern' after skipping arbitrary leading
- whitespace. After successfully matching 'pattern', skip trailing
- whitespace as well.
-
- 'pattern' is NOT a regular expression, but a bytes string in which
- each space character matches zero or more whitespace characters in the
- stream. Non-space characters are matched case-insensitively.
-
- If 'pattern' matches, return True and leave our input stream advanced
- past the last byte examined.
-
- If 'pattern' does not match, return False and reset our input stream
- to its previous read position.
- """
- oldpos = self._stream.tell()
- for chunk in pattern.split():
- # skip leading space before this chunk
- c = self._next_nonblank()
- # if we hit EOF, no match
- if not c:
- self._stream.seek(oldpos)
- return False
- # not EOF: try to match non-empty chunk,
- # not forgetting that 'c' is a lookahead byte
- # (split() never produces a zero-length chunk)
- maybe = c + self._stream.read(len(chunk)-1)
- if maybe.lower() != chunk.lower():
- # mismatch, reset
- self._stream.seek(oldpos)
- return False
- # so far so good, back for next chunk
-
- # here we've matched every chunk, with the read pointer just at the end of
- # the last matched chunk -- skip trailing space
- if self._next_nonblank():
- # back up one character, i.e. put back the nonblank
- self._stream.seek(-1, io.SEEK_CUR)
- # success!
- return True
-
- def remainder(self):
- # return a stream object representing the parse input (from last
- # _reset() call), whose read position is set past scanned input
- return self._stream
-
- def _next_nonblank(self):
- # we directly call read() rather than getc() because our caller is
- # prepared to handle empty string, meaning EOF
- # (YES we want the walrus operator)
- c = self._stream.read(1)
- while c.isspace():
- c = self._stream.read(1)
- return c
-
- def _getc(self, num=1, full=True):
- got = self._stream.read(num)
- if full and len(got) < num:
- self._error("Trying to read past end of stream")
- return got
-
- def _putback(self, cc):
- # if this test fails, it's not a user error, it's a coding error
- assert self._stream.tell() >= len(cc)
- self._stream.seek(-len(cc), io.SEEK_CUR)
-
- def _error(self, message, offset=0):
- oldpos = self._stream.tell()
- # 'offset' is relative to current pos
- self._stream.seek(offset, io.SEEK_CUR)
- raise LLSDParseError("%s at byte %d: %r" %
- (message, oldpos+offset, self._getc(1, full=False)))
-
- # map char following escape char to corresponding character
- _escaped = {
- ord(b'a'): ord(b'\a'),
- ord(b'b'): ord(b'\b'),
- ord(b'f'): ord(b'\f'),
- ord(b'n'): ord(b'\n'),
- ord(b'r'): ord(b'\r'),
- ord(b't'): ord(b'\t'),
- ord(b'v'): ord(b'\v'),
- }
-
- def _parse_string_delim(self, delim):
- "Parse a delimited string."
- insert_idx = 0
- delim_ord = ord(delim)
- # Preallocate a working buffer for the decoded string output
- # to avoid allocs in the hot loop.
- decode_buff = self._decode_buff
- # Cache this in locals, otherwise we have to perform a lookup on
- # `self` in the hot loop.
- getc = self._getc
- cc = 0
- while True:
- try:
- cc = ord(getc())
-
- if cc == _BACKSLASH_ORD:
- # Backslash, figure out if this is an \xNN hex escape or
- # something like \t
- cc = ord(getc())
- if cc == _X_ORD:
- # It's a hex escape. char is the value of the two
- # following hex nybbles. This slice may result in
- # a short read (0 or 1 bytes), but either a
- # `ValueError` will be triggered by the first case,
- # and the second will cause an `IndexError` on the
- # next iteration of the loop.
- hex_bytes = getc(2)
- try:
- # int() can parse a `bytes` containing hex,
- # no explicit `bytes.decode("ascii")` required.
- cc = int(hex_bytes, 16)
- except ValueError as e:
- # One of the hex characters was likely invalid.
- # Wrap the ValueError so that we can provide a
- # byte offset in the error.
- self._error(e, offset=-2)
- else:
- # escape char preceding anything other than the chars
- # in _escaped just results in that same char without
- # the escape char
- cc = self._escaped.get(cc, cc)
- elif cc == delim_ord:
- break
- except IndexError:
- # We can be reasonably sure that any IndexErrors inside here
- # were caused by an out-of-bounds `buff[read_idx]`.
- self._error("Trying to read past end of buffer")
-
- try:
- decode_buff[insert_idx] = cc
- except IndexError:
- # Oops, that overflowed the decoding buffer, make a
- # new expanded buffer containing the existing contents.
- decode_buff = bytearray(decode_buff)
- decode_buff.extend(b"\x00" * _DECODE_BUFF_ALLOC_SIZE)
- decode_buff[insert_idx] = cc
-
- insert_idx += 1
-
- # Sync our local read index with the canonical one
- try:
- # Slice off only what we used of the working decode buffer
- return decode_buff[:insert_idx].decode('utf-8')
- except UnicodeDecodeError as exc:
- self._error(exc)
diff --git a/llsd/fastest_elementtree.py b/llsd/fastest_elementtree.py
deleted file mode 100644
index 0f89f8e..0000000
--- a/llsd/fastest_elementtree.py
+++ /dev/null
@@ -1,65 +0,0 @@
-"""
-Concealing some gnarly import logic in here. This should export
-the interface of elementtree.
-
-The parsing exception raised by the underlying library depends on the
-ElementTree implementation we're using, so we provide an alias here.
-
-Generally, you can use this module as a drop in replacement for how
-you would use ElementTree or cElementTree.
-
-
-from fastest_elementtree import fromstring
-fromstring(...)
-
-
-Use ElementTreeError as the exception type for catching parsing
-errors.
-"""
-
-# TODO: drop version sensitivity, replacing entire module with:
-#from xml.etree.ElementTree import *
-#ElementTreeError = ParseError
-
-##
-# Using cElementTree might cause some unforeseen problems, so here's a
-# convenient off switch during development and testing.
-_use_celementree = True
-
-# xml.etree.cElementTree has been deprecated since Python 3.3.
-# For speed in the common case of Python 3.3+, don't even start with that.
-import sys
-if sys.version_info[:2] >= (3, 3):
- _use_celementree = False
-
-try:
- # nat wishes for a nicer way to skip even attempting cElementTree than by
- # explicitly raising ImportError. The problem is that we want to be able
- # to 'import *' into the global namespace, which forbids packaging any of
- # this logic in a function. Nor can we 'return' early from a module. It
- # seems the only way to avoid the explicit exception would be to restate
- # the entirety of each 'except ImportError' clause, which would be worse.
- if not _use_celementree:
- raise ImportError()
- # Python 2.5 and above.
- from xml.etree.cElementTree import *
- ElementTreeError = SyntaxError
-except ImportError:
- try:
- # Python 2.5 and above: the common case.
- from xml.etree.ElementTree import *
- try:
- # Python 3
- ElementTreeError = ParseError
- except NameError:
- # The older Python ElementTree module uses Expat for parsing.
- from xml.parsers.expat import ExpatError as ElementTreeError
- except ImportError:
- # Python 2.3 and 2.4.
- try:
- if not _use_celementree:
- raise ImportError()
- from cElementTree import *
- ElementTreeError = SyntaxError
- except ImportError:
- from elementtree.ElementTree import *
diff --git a/llsd/serde_binary.py b/llsd/serde_binary.py
deleted file mode 100644
index e4ac7c5..0000000
--- a/llsd/serde_binary.py
+++ /dev/null
@@ -1,262 +0,0 @@
-import calendar
-import datetime
-import io
-import struct
-import uuid
-
-from llsd.base import (_LLSD, LLSDBaseParser, LLSDSerializationError, BINARY_HEADER,
- MAX_FORMAT_DEPTH, MAX_PARSE_DEPTH, _str_to_bytes, binary, is_integer, is_string, uri)
-
-
-try:
- # Python 2: make 'range()' lazy like Python 3
- range = xrange
-except NameError:
- # Python 3: 'range()' is already lazy
- pass
-
-class LLSDBinaryParser(LLSDBaseParser):
- """
- Parse application/llsd+binary to a python object.
-
- See http://wiki.secondlife.com/wiki/LLSD#Binary_Serialization
- """
- __slots__ = ['_dispatch', '_keep_binary', '_depth']
-
- def __init__(self):
- super(LLSDBinaryParser, self).__init__()
- # One way of dispatching based on the next character we see would be a
- # dict lookup, and indeed that's the best way to express it in source.
- _dispatch_dict = {
- b'{': self._parse_map,
- b'[': self._parse_array,
- b'!': lambda: None,
- b'0': lambda: False,
- b'1': lambda: True,
- # 'i' = integer
- b'i': lambda: struct.unpack("!i", self._getc(4))[0],
- # 'r' = real number
- b'r': lambda: struct.unpack("!d", self._getc(8))[0],
- # 'u' = uuid
- b'u': lambda: uuid.UUID(bytes=self._getc(16)),
- # 's' = string
- b's': self._parse_string,
- # delimited/escaped string
- b"'": lambda: self._parse_string_delim(b"'"),
- b'"': lambda: self._parse_string_delim(b'"'),
- # 'l' = uri
- b'l': lambda: uri(self._parse_string()),
- # 'd' = date in seconds since epoch
- b'd': self._parse_date,
- # 'b' = binary
- # *NOTE: if not self._keep_binary, maybe have a binary placeholder
- # which has the length.
- b'b': lambda: bytes(self._parse_string_raw()) if self._keep_binary else None,
- }
- # But in fact it should be even faster to construct a list indexed by
- # ord(char). Start by filling it with the 'else' case. Use offset=-1
- # because by the time we perform this lookup, we've scanned past the
- # lookup char.
- self._dispatch = 256*[lambda: self._error("invalid binary token", -1)]
- # Now use the entries in _dispatch_dict to set the corresponding
- # entries in _dispatch.
- for c, func in _dispatch_dict.items():
- self._dispatch[ord(c)] = func
- self._depth = 0
-
- def parse(self, something, ignore_binary = False):
- """
- This is the basic public interface for parsing.
-
- :param something: serialized LLSD to parse: a bytes object, a binary
- stream or an LLSDBaseParser subclass.
- :param ignore_binary: parser throws away data in llsd binary nodes.
- :returns: returns a python object.
- """
- self._reset(something)
- self._keep_binary = not ignore_binary
- try:
- return self._parse()
- except struct.error as exc:
- self._error(exc)
-
- def _parse(self):
- "The actual parser which is called recursively when necessary."
- if self._depth > MAX_PARSE_DEPTH:
- self._error("Parse depth exceeded maximum depth of %d." % MAX_PARSE_DEPTH)
-
- cc = self._getc()
- try:
- func = self._dispatch[ord(cc)]
- except IndexError:
- self._error("invalid binary token", -1)
- else:
- return func()
-
- def _parse_map(self):
- "Parse a single llsd map"
- rv = {}
- size = struct.unpack("!i", self._getc(4))[0]
- count = 0
- cc = self._getc()
- key = b''
- self._depth += 1
- while (cc != b'}') and (count < size):
- if cc == b'k':
- key = self._parse_string()
- elif cc in (b"'", b'"'):
- key = self._parse_string_delim(cc)
- else:
- self._error("invalid map key", -1)
- value = self._parse()
- rv[key] = value
- count += 1
- cc = self._getc()
- if cc != b'}':
- self._error("invalid map close token")
- self._depth -= 1
- return rv
-
- def _parse_array(self):
- "Parse a single llsd array"
- rv = []
- self._depth += 1
- size = struct.unpack("!i", self._getc(4))[0]
- for count in range(size):
- rv.append(self._parse())
- if self._getc() != b']':
- self._error("invalid array close token")
- self._depth -= 1
- return rv
-
- def _parse_string(self):
- try:
- return self._parse_string_raw().decode('utf-8')
- except UnicodeDecodeError as exc:
- self._error(exc)
-
- def _parse_string_raw(self):
- "Parse a string which has the leadings size indicator"
- try:
- size = struct.unpack("!i", self._getc(4))[0]
- except struct.error as exc:
- # convert exception class for client convenience
- self._error("struct " + str(exc))
- rv = self._getc(size)
- return rv
-
- def _parse_date(self):
- seconds = struct.unpack("\n')
- _write_binary_recurse(stream, something, 0)
-
-
-def _write_binary_recurse(stream, something, depth):
- "Binary formatter workhorse."
-
- if depth > MAX_FORMAT_DEPTH:
- raise LLSDSerializationError("Cannot serialize depth of more than %d" % MAX_FORMAT_DEPTH)
-
- if something is None:
- stream.write(b'!')
- elif isinstance(something, _LLSD):
- _write_binary_recurse(stream, something.thing, depth)
- elif isinstance(something, bool):
- stream.write(b'1' if something else b'0')
- elif is_integer(something):
- try:
- stream.writelines([b'i', struct.pack('!i', something)])
- except (OverflowError, struct.error) as exc:
- raise LLSDSerializationError(str(exc), something)
- elif isinstance(something, float):
- try:
- stream.writelines([b'r', struct.pack('!d', something)])
- except SystemError as exc:
- raise LLSDSerializationError(str(exc), something)
- elif isinstance(something, uuid.UUID):
- stream.writelines([b'u', something.bytes])
- elif isinstance(something, binary):
- stream.writelines([b'b', struct.pack('!i', len(something)), something])
- elif is_string(something):
- something = _str_to_bytes(something)
- stream.writelines([b's', struct.pack('!i', len(something)), something])
- elif isinstance(something, uri):
- stream.writelines([b'l', struct.pack('!i', len(something)), something])
- elif isinstance(something, datetime.datetime):
- seconds_since_epoch = calendar.timegm(something.utctimetuple()) \
- + something.microsecond // 1e6
- stream.writelines([b'd', struct.pack(' MAX_PARSE_DEPTH:
- self._error("Parse depth exceeded max of %d" % MAX_PARSE_DEPTH)
- try:
- func = self._dispatch[ord(cc)]
- except IndexError:
- # output error if the token was out of range
- self._error("Invalid notation token")
- else:
- # pass the lookahead character that selected this func
- return func(cc)
-
- def _parse_binary(self, cc):
- "parse a single binary object."
-
- # skip the beginning 'b'
- cc = self._getc()
- if cc == b'(':
- # parse raw binary
- # grab the 'expected' size of the binary data
- size = self._get_until(b')')
- if size == None:
- self._error("Invalid binary size")
- size = int(size)
-
- # grab the opening quote
- q = self._getc()
- if q != b'"':
- self._error('Expected " to start binary value')
-
- # grab the data
- data = self._getc(size)
-
- # grab the closing quote
- q = self._getc()
- if q != b'"':
- self._error('Expected " to end binary value')
-
- return binary(data)
-
- else:
- # get the encoding base
- base = cc + self._getc()
- try:
- decoder = {
- b'16': base64.b16decode,
- b'64': base64.b64decode,
- }[base]
- except KeyError:
- self._error("Parser doesn't support base %s encoding" %
- base.decode('latin-1'))
-
- # grab the double quote
- q = self._getc()
- if q != b'"':
- self._error('Expected " to start binary value')
-
- # grab the encoded data
- encoded = self._get_until(q)
-
- try:
- return binary(decoder(encoded or b''))
- except binascii.Error as exc:
- # convert exception class so it's more catchable
- self._error("Encoded binary data: " + str(exc))
- except TypeError as exc:
- # convert exception class so it's more catchable
- self._error("Bad binary data: " + str(exc))
-
- def _parse_map(self, cc):
- """
- parse a single map
-
- map: { string:object, string:object }
- """
- rv = {}
- key = b''
- found_key = False
- self._depth += 1
- # skip the beginning '{'
- cc = self._getc()
- while (cc != b'}'):
- if cc is None:
- self._error("Unclosed map")
- if not found_key:
- if cc in (b"'", b'"', b's'):
- key = self._parse_string(cc)
- found_key = True
- elif cc.isspace() or cc == b',':
- # ignore space or comma
- pass
- else:
- self._error("Invalid map key")
- elif cc.isspace():
- # ignore space
- pass
- elif cc == b':':
- # skip the ':'
- value = self._parse(self._getc())
- rv[key] = value
- found_key = False
- else:
- self._error("missing separator")
- cc = self._getc()
- self._depth -= 1
-
- return rv
-
- def _parse_array(self, cc):
- """
- parse a single array.
-
- array: [ object, object, object ]
- """
- rv = []
- self._depth += 1
- # skip the beginning '['
- cc = self._getc()
- while (cc != b']'):
- if cc is None:
- self._error('Unclosed array')
- if cc.isspace() or cc == b',':
- cc = self._getc()
- continue
- rv.append(self._parse(cc))
- cc = self._getc()
- self._depth -= 1
- return rv
-
- def _parse_uuid(self, cc):
- "Parse a uuid."
- # ignore the beginning 'u'
- # see comment on LLSDNotationFormatter._UUID() re use of latin-1
- return uuid.UUID(hex=self._getc(36).decode('latin-1'))
-
- def _parse_uri(self, cc):
- "Parse a URI."
- # skip the beginning 'l'
- return uri(self._parse_string(self._getc()))
-
- def _parse_date(self, cc):
- "Parse a date."
- # skip the beginning 'd'
- datestr = self._parse_string(self._getc())
- return _parse_datestr(datestr)
-
- def _parse_real(self, cc):
- "Parse a floating point number."
- # recognize:
- # [+-]?inf
- # [+-]?nan
- # [+-]?basepart([eE][+-]?\d+)?
- # where basepart could be either:
- # \d+(\.\d*)? or
- # \d*\.\d+
- digits = []
- # skip the beginning 'r'
- cc = self._collect_sign(self._getc(), digits)
- try:
- rest = {b'i': b'nf', b'n': b'an'}[cc]
- except KeyError:
- # cc is neither 'i' nor 'n', must be a digit:
- # collect integer digits
- idigits = []
- fdigits = []
- edigits = []
- cc = self._collect_digits(cc, idigits)
- digits.extend(idigits)
- if cc == b'.':
- digits.append(cc)
- # skip decimal point and collect fractional digits
- cc = self._collect_digits(self._getc(full=False), fdigits)
- digits.extend(fdigits)
- # Fun fact: (cc in b'eE') is True even when cc is b''!
- if cc in (b'e', b'E'):
- digits.append(cc)
- # skip 'e' and check for exponent sign
- cc = self._collect_sign(self._getc(), digits)
- cc = self._collect_digits(cc, edigits)
- digits.extend(edigits)
- if not edigits:
- # if 'e' is present, there MUST be an exponent
- self._error('Invalid real exponent')
- # Whether this real number ended after the integer part, after the
- # decimal point, after the fractional part or after the exponent,
- # cc is now one character PAST the end -- put it back.
- self._putback(cc)
- # The reason we collected idigits and fdigits separately is that
- # while either may be empty, they may not BOTH be empty.
- if not (idigits or fdigits):
- self._error('Invalid real number')
- else:
- # cc is either 'i' for 'inf' or 'n' for 'nan',
- # rest is 'nf' or 'an'
- digits.extend([cc, self._expect(cc + rest, rest)])
-
- return float(b''.join(digits))
-
- def _parse_integer(self, cc):
- "Parse an integer."
- digits = []
- # skip the beginning 'i'
- cc = self._collect_sign(self._getc(), digits)
- cc = self._collect_digits(cc, digits)
- if not digits:
- self._error('Invalid integer token')
-
- # cc is now the next _getc() after the last digit -- back up
- self._putback(cc)
-
- return int(b''.join(digits))
-
- def _collect_sign(self, cc, digits):
- if cc in (b'+', b'-'):
- digits.append(cc)
- cc = self._getc()
- return cc
-
- def _collect_digits(self, cc, digits):
- while cc.isdigit():
- digits.append(cc)
- # we can accept EOF happening here
- cc = self._getc(full=False)
- return cc
-
- def _parse_string(self, delim):
- """
- Parse a string
-
- string: "g\'day" | 'have a "nice" day' | s(size)"raw data"
- """
- rv = ""
- if delim in (b"'", b'"'):
- rv = self._parse_string_delim(delim)
- elif delim == b's':
- rv = self._parse_string_raw()
- else:
- self._error("invalid string token")
-
- return rv
-
- def _parse_string_raw(self):
- """
- Parse a sized specified string.
-
- string: s(size)"raw data"
- """
- # Read the (size) portion.
- cc = self._getc()
- if cc != b'(':
- self._error("Invalid string token")
-
- size = self._get_until(b')')
- if size == None:
- self._error("Invalid string size")
- size = int(size)
-
- delim = self._getc()
- if delim not in (b"'", b'"'):
- self._error("Invalid string token")
-
- rv = self._getc(size)
- cc = self._getc()
- if cc != delim:
- self._error("Invalid string closure token")
- try:
- return rv.decode('utf-8')
- except UnicodeDecodeError as exc:
- raise LLSDParseError(exc)
-
- def _parse_true(self, cc):
- # match t, T, true, TRUE -- not mixed-case
- return self._parse_bool(cc, True, (b'true', b'TRUE'))
-
- def _parse_false(self, cc):
- # match f, F, false, FALSE -- not mixed-case
- return self._parse_bool(cc, False, (b'false', b'FALSE'))
-
- def _parse_bool(self, cc, result, tokens):
- try:
- # Index on first character to find expected rest.
- # Beware, token is bytes, so token[0] is an int!
- rest = {token[:1]: token[1:] for token in tokens}[cc]
- except KeyError:
- self._error("Invalid '%s' token" % tokens[0])
-
- cc = self._getc(full=False)
- if cc != rest[:1]:
- # legal to have only first char, put back cc and carry on
- self._putback(cc)
- return result
-
- # saw 'tr' or 'TR' (or 'fa' or 'FA'), cc is the second char:
- # MUST be followed by the rest of 'rest'
- self._expect(tokens[0], rest[1:])
- return result
-
- def _expect(self, token, match):
- # verify that the next several chars are exactly what we expect
- if self._getc(len(match), full=False) != match:
- self._error("Invalid '%s' token" % token)
- return match
-
-
-class LLSDNotationFormatter(LLSDBaseFormatter):
- """
- Serialize a python object as application/llsd+notation
-
- See http://wiki.secondlife.com/wiki/LLSD#Notation_Serialization
- """
-
- def __init__(self):
- super(LLSDNotationFormatter, self).__init__()
- self._depth = 0
-
- def _LLSD(self, v):
- return self._generate(v.thing)
- def _UNDEF(self, v):
- self.stream.write(b'!')
- def _BOOLEAN(self, v):
- self.stream.write(b'true' if v else b'false')
- def _INTEGER(self, v):
- self.stream.write(B("i%d") % v)
- def _REAL(self, v):
- self.stream.write(B("r%r") % v)
- def _UUID(self, v):
- # latin-1 is the byte-to-byte encoding, mapping \x00-\xFF ->
- # \u0000-\u00FF. It's also the fastest encoding, I believe, from
- # https://docs.python.org/3/library/codecs.html#encodings-and-unicode
- # UUID doesn't like the hex to be a bytes object, so I have to
- # convert it to a string. I chose latin-1 to exactly match the old
- # error behavior in case someone passes an invalid hex string, with
- # things other than 0-9a-fA-F, so that they will fail in the UUID
- # decode, rather than with a UnicodeError.
- self.stream.writelines([b"u", str(v).encode('latin-1')])
- def _BINARY(self, v):
- self.stream.writelines([b'b64"', base64.b64encode(v).strip(), b'"'])
-
- def _STRING(self, v):
- self.stream.writelines([b"'", self._esc(v), b"'"])
- def _URI(self, v):
- self.stream.writelines([b'l"', self._esc(v, b'"'), b'"'])
- def _DATE(self, v):
- self.stream.writelines([b'd"', _format_datestr(v), b'"'])
- def _ARRAY(self, v):
- self.stream.write(b'[')
- delim = b''
- self._depth += 1
- for item in v:
- self.stream.write(delim)
- self._generate(item)
- delim = b','
- self._depth -= 1
- self.stream.write(b']')
- def _MAP(self, v):
- self.stream.write(b'{')
- delim = b''
- self._depth += 1
- for key, value in v.items():
- self.stream.writelines([delim, b"'", self._esc(UnicodeType(key)), b"':"])
- self._generate(value)
- delim = b','
- self._depth -= 1
- self.stream.write(b'}')
-
- def _esc(self, data, quote=b"'"):
- return _str_to_bytes(data).replace(b"\\", b"\\\\").replace(quote, b'\\'+quote)
-
- def _generate(self, something):
- """
- Serialize a python object to self.stream as application/llsd+notation
-
- :param something: a python object (typically a dict) to be serialized.
- """
- if self._depth > MAX_FORMAT_DEPTH:
- raise LLSDSerializationError("Cannot serialize depth of more than %d" % MAX_FORMAT_DEPTH)
-
- t = type(something)
- handler = self.type_map.get(t)
- if handler:
- return handler(something)
- elif isinstance(something, _LLSD):
- return self.type_map[_LLSD](something)
- else:
- try:
- return self._ARRAY(iter(something))
- except TypeError:
- raise LLSDSerializationError(
- "Cannot serialize unknown type: %s (%s)" % (t, something))
-
- # _write() method is an alias for _generate()
- _write = _generate
-
-
-def format_notation(something):
- """
- Format a python object as application/llsd+notation
-
- :param something: a python object (typically a dict) to be serialized.
- :returns: Returns a LLSD notation formatted string.
-
- See http://wiki.secondlife.com/wiki/LLSD#Notation_Serialization
- """
- return LLSDNotationFormatter().format(something)
-
-
-def write_notation(stream, something):
- """
- Serialize to passed binary 'stream' a python object 'something' as
- application/llsd+notation.
-
- :param stream: a binary stream open for writing.
- :param something: a python object (typically a dict) to be serialized.
-
- See http://wiki.secondlife.com/wiki/LLSD#Notation_Serialization
- """
- return LLSDNotationFormatter().write(stream, something)
-
-
-def parse_notation(something):
- """
- This is the basic public interface for parsing llsd+notation.
-
- :param something: The data to parse.
- :returns: Returns a python object.
- """
- # Try to match header, and if matched, skip past it.
- parser = LLSDBaseParser(something)
- parser.matchseq(NOTATION_HEADER)
- # If we matched the header, then parse whatever follows, else parse the
- # original bytes object or stream.
- return parse_notation_nohdr(parser)
-
-
-def parse_notation_nohdr(baseparser):
- """
- Parse llsd+notation known to be without a header.
-
- :param baseparser: LLSDBaseParser instance wrapping the data to parse.
- :returns: Returns a python object.
- """
- return LLSDNotationParser().parse(baseparser)
diff --git a/llsd/serde_xml.py b/llsd/serde_xml.py
deleted file mode 100644
index 3833f57..0000000
--- a/llsd/serde_xml.py
+++ /dev/null
@@ -1,299 +0,0 @@
-import base64
-import io
-import re
-
-from llsd.base import (_LLSD, ALL_CHARS, LLSDBaseParser, LLSDBaseFormatter, XML_HEADER,
- MAX_FORMAT_DEPTH, LLSDParseError, LLSDSerializationError, UnicodeType,
- _format_datestr, _str_to_bytes, _to_python, is_unicode, PY2)
-from llsd.fastest_elementtree import ElementTreeError, fromstring, parse as _parse
-
-INVALID_XML_BYTES = b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0b\x0c'\
- b'\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18'\
- b'\x19\x1a\x1b\x1c\x1d\x1e\x1f'
-INVALID_XML_RE = re.compile(r'[\x00-\x08\x0b\x0c\x0e-\x1f]')
-
-
-XML_ESC_TRANS = {}
-if not PY2:
- XML_ESC_TRANS = str.maketrans({'&': '&',
- '<':'<',
- '>':'>',
- u'\uffff':None, # cannot be parsed
- u'\ufffe':None}) # cannot be parsed
-
- for x in INVALID_XML_BYTES:
- XML_ESC_TRANS[x] = None
-
-def remove_invalid_xml_bytes(b):
- """
- Remove characters that aren't allowed in xml.
- """
- try:
- # Dropping chars that cannot be parsed later on. The
- # translate() function was benchmarked to be the fastest way
- # to do this.
- return b.translate(ALL_CHARS, INVALID_XML_BYTES)
- except TypeError:
- # we get here if s is a unicode object (should be limited to
- # unit tests)
- return INVALID_XML_RE.sub('', b)
-
-# only python2, which is not covered by coverage tests
-def xml_esc(v): # pragma: no cover
- "Escape string or unicode object v for xml output"
-
- # Use is_unicode() instead of is_string() because in python 2, str is
- # bytes, not unicode, and should not be "encode()"d. Attempts to
- # encode("utf-8") a bytes type will result in an implicit
- # decode("ascii") that will throw a UnicodeDecodeError if the string
- # contains non-ascii characters.
- if is_unicode(v):
- # we need to drop these invalid characters because they
- # cannot be parsed (and encode() doesn't drop them for us)
- v = v.replace(u'\uffff', u'')
- v = v.replace(u'\ufffe', u'')
- v = v.encode('utf-8')
- v = remove_invalid_xml_bytes(v)
- return v.replace(b'&',b'&').replace(b'<',b'<').replace(b'>',b'>')
-
-
-class LLSDXMLFormatter(LLSDBaseFormatter):
- """
- Class which implements LLSD XML serialization.
-
- http://wiki.secondlife.com/wiki/LLSD#XML_Serialization
-
- This class serializes a limited subset of python objects as
- application/llsd+xml. You do not generally need to make an instance of
- this class since the module level format_xml() is the most convenient
- interface to this functionality.
- """
-
- def __init__(self, indent_atom = b'', eol = b''):
- "Construct a serializer."
- # Call the super class constructor so that we have the type map
- super(LLSDXMLFormatter, self).__init__()
- self._indent_atom = indent_atom
- self._eol = eol
- self._depth = 1
-
- def _indent(self):
- pass
-
- def _LLSD(self, v):
- return self._generate(v.thing)
- def _UNDEF(self, _v):
- self.stream.writelines([b' ', self._eol])
- def _BOOLEAN(self, v):
- if v:
- return self.stream.writelines([b'true ', self._eol])
- self.stream.writelines([b'false ', self._eol])
- def _INTEGER(self, v):
- self.stream.writelines([b'', str(v).encode('utf-8'), b' ', self._eol])
- def _REAL(self, v):
- self.stream.writelines([b'', str(v).encode('utf-8'), b' ', self._eol])
- def _UUID(self, v):
- if v.int == 0:
- return self.stream.writelines([b' ', self._eol])
- self.stream.writelines([b'', str(v).encode('utf-8'), b' ', self._eol])
- def _BINARY(self, v):
- self.stream.writelines([b'', base64.b64encode(v).strip(), b' ', self._eol])
-
- if PY2:
- def _STRING(self, v):
- return self.stream.writelines([b'', _str_to_bytes(xml_esc(v)), b' ', self._eol])
- def _URI(self, v):
- return self.stream.writelines([b'', _str_to_bytes(xml_esc(v)), b' ', self._eol])
- else:
- def _STRING(self, v):
- self.stream.writelines([b'', v.translate(XML_ESC_TRANS).encode('utf-8'), b' ', self._eol])
- def _URI(self, v):
- self.stream.writelines([b'', str(v).translate(XML_ESC_TRANS).encode('utf-8'), b' ', self._eol])
-
- def _DATE(self, v):
- self.stream.writelines([b'', _format_datestr(v), b' ', self._eol])
- def _ARRAY(self, v):
- self.stream.writelines([b'', self._eol])
- self._depth += 1
- for item in v:
- self._indent()
- self._generate(item)
- self._depth -= 1
- self._indent()
- self.stream.writelines([b' ', self._eol])
- def _MAP(self, v):
- self.stream.writelines([b'', self._eol])
- self._depth += 1
- for key, value in v.items():
- self._indent()
- if PY2: # pragma: no cover
- self.stream.writelines([b'',
- xml_esc(UnicodeType(key)),
- b' ',
- self._eol])
- else:
- self.stream.writelines([b'',
- UnicodeType(key).translate(XML_ESC_TRANS).encode('utf-8'),
- b' ',
- self._eol])
- self._indent()
- self._generate(value)
- self._depth -= 1
- self._indent()
- self.stream.writelines([b' ', self._eol])
-
- def _generate(self, something):
- "Generate xml from a single python object."
- if self._depth - 1 > MAX_FORMAT_DEPTH:
- raise LLSDSerializationError("Cannot serialize depth of more than %d" % MAX_FORMAT_DEPTH)
- t = type(something)
- if t in self.type_map:
- return self.type_map[t](something)
- elif isinstance(something, _LLSD):
- return self.type_map[_LLSD](something)
- else:
- raise LLSDSerializationError(
- "Cannot serialize unknown type: %s (%s)" % (t, something))
-
- def _write(self, something):
- """
- Serialize a python object to self.stream as application/llsd+xml.
- :param something: A python object (typically a dict) to be serialized.
- """
- self.stream.writelines([b'', self._eol,
- b'', self._eol])
- self._generate(something)
- self.stream.write(b' ' + self._eol)
-
-
-class LLSDXMLPrettyFormatter(LLSDXMLFormatter):
- """
- Class which implements 'pretty' LLSD XML serialization..
-
- See http://wiki.secondlife.com/wiki/LLSD#XML_Serialization
-
- The output conforms to the LLSD DTD, unlike the output from the
- standard python xml.dom DOM::toprettyxml() method which does not
- preserve significant whitespace.
-
- This class is not necessarily suited for serializing very large objects.
- It sorts on dict (llsd map) keys alphabetically to ease human reading.
- """
- def __init__(self, indent_atom = b' ', eol = b'\n'):
- "Construct a pretty serializer."
- # Call the super class constructor so that we have the type map
- super(LLSDXMLPrettyFormatter, self).__init__(indent_atom = indent_atom, eol = eol)
-
- def _indent(self):
- "Write an indentation based on the atom and indentation level."
- self.stream.writelines([self._indent_atom] * self._depth)
-
-
-def format_pretty_xml(something):
- """
- Serialize a python object as 'pretty' application/llsd+xml.
-
- :param something: a python object (typically a dict) to be serialized.
- :returns: Returns an XML formatted string.
-
- See http://wiki.secondlife.com/wiki/LLSD#XML_Serialization
-
- The output conforms to the LLSD DTD, unlike the output from the
- standard python xml.dom DOM::toprettyxml() method which does not
- preserve significant whitespace.
- This function is not necessarily suited for serializing very large
- objects. It sorts on dict (llsd map) keys alphabetically to ease human
- reading.
- """
- return LLSDXMLPrettyFormatter().format(something)
-
-
-def write_pretty_xml(stream, something):
- """
- Serialize to passed 'stream' the python object 'something' as 'pretty'
- application/llsd+xml.
-
- :param stream: a binary stream open for writing.
- :param something: a python object (typically a dict) to be serialized.
-
- See http://wiki.secondlife.com/wiki/LLSD#XML_Serialization
-
- The output conforms to the LLSD DTD, unlike the output from the
- standard python xml.dom DOM::toprettyxml() method which does not
- preserve significant whitespace.
- This function is not necessarily suited for serializing very large
- objects. It sorts on dict (llsd map) keys alphabetically to ease human
- reading.
- """
- return LLSDXMLPrettyFormatter().write(stream, something)
-
-
-def parse_xml(something):
- """
- This is the basic public interface for parsing llsd+xml.
-
- :param something: The data to parse.
- :returns: Returns a python object.
- """
- # Try to match header, and if matched, skip past it.
- parser = LLSDBaseParser(something)
- parser.matchseq(XML_HEADER)
- # If we matched the header, then parse whatever follows, else parse the
- # original bytes object or stream.
- return parse_xml_nohdr(parser)
-
-
-def parse_xml_nohdr(baseparser):
- """
- Parse llsd+xml known to be without an LLSD/XML ?> header. May still
- have a normal XML declaration, e.g. .
-
- :param baseparser: LLSDBaseParser instance wrapping the data to parse.
- :returns: Returns a python object.
- """
- # Python 3.9's xml.etree.ElementTree.fromstring() does not like whitespace
- # before XML declaration. Since we explicitly test support for that case,
- # skip initial whitespace.
- baseparser.matchseq(b'')
- stream = baseparser.remainder()
- try:
- if isinstance(stream, io.BytesIO):
- # Empirically, fromstring() seems faster than _parse(). If passed
- # a BytesIO, extract its contents and skip to BytesIO read pos.
- element = fromstring(stream.getvalue()[stream.tell():])
- else:
- # Not a BytesIO, parse the stream
- element = _parse(stream).getroot()
- except ElementTreeError as err:
- raise LLSDParseError(*err.args)
-
- # We expect that the outer-level XML element is ... .
- if element.tag != 'llsd':
- raise LLSDParseError("Invalid XML Declaration")
- # Extract its contents.
- return _to_python(element[0])
-
-
-def format_xml(something):
- """
- Format a python object as application/llsd+xml
-
- :param something: a python object (typically a dict) to be serialized.
- :returns: Returns an XML formatted string.
-
- See http://wiki.secondlife.com/wiki/LLSD#XML_Serialization
- """
- return LLSDXMLFormatter().format(something)
-
-
-def write_xml(stream, something):
- """
- Serialize to passed 'stream' the python object 'something' as
- application/llsd+xml.
-
- :param stream: a binary stream open for writing.
- :param something: a python object (typically a dict) to be serialized.
-
- See http://wiki.secondlife.com/wiki/LLSD#XML_Serialization
- """
- return LLSDXMLFormatter().write(stream, something)
diff --git a/setup.py b/setup.py
deleted file mode 100644
index db8beb0..0000000
--- a/setup.py
+++ /dev/null
@@ -1,35 +0,0 @@
-import os
-
-from setuptools import find_packages, setup
-
-root_dir = os.path.dirname(__file__)
-with open(os.path.join(root_dir, "README.md")) as f:
- long_description = f.read()
-
-
-setup(
- name="llsd",
- url="https://github.com/secondlife/python-llsd",
- license="MIT",
- author="Linden Research, Inc.",
- author_email="opensource-dev@lists.secondlife.com",
- description="Linden Lab Structured Data (LLSD) serialization library",
- long_description=long_description,
- long_description_content_type="text/markdown",
- packages=find_packages(exclude=("tests",)),
- setup_requires=["setuptools_scm<6"],
- use_scm_version={
- 'local_scheme': 'no-local-version', # disable local-version to allow uploads to test.pypi.org
- },
- extras_require={
- "dev": ["pytest", "pytest-benchmark", "pytest-cov<3"],
- },
- classifiers=[
- "Intended Audience :: Developers",
- "License :: OSI Approved :: MIT License",
- "Programming Language :: Python :: 2",
- "Programming Language :: Python :: 3",
- "Topic :: Software Development :: Libraries :: Python Modules",
- "Topic :: Software Development",
- ],
-)
diff --git a/tests/__init__.py b/tests/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/tests/bench.py b/tests/bench.py
deleted file mode 100644
index 722e67b..0000000
--- a/tests/bench.py
+++ /dev/null
@@ -1,196 +0,0 @@
-from tempfile import TemporaryFile
-import unittest
-
-import pytest
-
-import llsd
-
-BENCH_DATA_XML = b"""
-
-
- integer
- 5000
- real
- 0.096970
- binary
- ff55ca5cef2f477f92e011c7de95bb11
- uri
- https://secondlife.com
- date
- 2006-02-01T14:29:53Z
- children
-
-
- integer
- 5000
- real
- 0.096970
- binary
- ff55ca5cef2f477f92e011c7de95bb11
- string
- AjWwhTHctcuAxhxK
- id
- ff55ca5cef2f477f92e011c7de95bb11
- int_32
- -1147906088
- bool
- 1
-
- 0.156519
- ff55ca5cef2f477f92e011c7de95bb11
- https://secondlife.com
- 2006-02-01T14:29:53Z
-
-
- """
-
-_bench_data = llsd.parse_xml(BENCH_DATA_XML)
-
-
-
-BENCH_DATA_BINARY = llsd.format_binary(_bench_data)
-BENCH_DATA_NOTATION = llsd.format_notation(_bench_data)
-
-_tc = unittest.TestCase()
-_tc.maxDiff = 5000
-assertDictEqual = _tc.assertDictEqual
-
-
-@pytest.fixture
-def xml_stream():
- with TemporaryFile() as f:
- f.write(BENCH_DATA_XML)
- f.seek(0)
- yield f
-
-
-@pytest.fixture
-def notation_stream():
- with TemporaryFile() as f:
- d = llsd.format_notation(_bench_data)
- f.write(d)
- f.seek(0)
- yield f
-
-
-@pytest.fixture
-def binary_stream():
- with TemporaryFile() as f:
- d = llsd.format_binary(_bench_data)
- f.write(d)
- f.seek(0)
- yield f
-
-def build_deep_xml():
- deep_data = {}
- curr_data = deep_data
- for i in range(198):
- curr_data["curr_data"] = {}
- curr_data["integer"] = 7
- curr_data["string"] = "string"
- curr_data["map"] = { "item1": 2.345, "item2": [1,2,3], "item3": {"item4": llsd.uri("http://foo.bar.com")}}
- curr_data = curr_data["curr_data"]
-
- return deep_data
-_deep_bench_data = build_deep_xml()
-
-def build_wide_xml():
-
- wide_xml = b"""
-wide_array "
-"""
- wide_data = {}
- for i in range(100000):
- wide_data["item"+str(i)] = {"item1":2.345, "item2": [1,2,3], "item3": "string", "item4":{"subitem": llsd.uri("http://foo.bar.com")}}
- return wide_data
-_wide_bench_data = build_wide_xml()
-
-def build_wide_array_xml():
-
- wide_xml = b"""
-wide_array "
-"""
- wide_data = []
- for i in range(100000):
- wide_data.append([2.345,[1,2,3], "string", [llsd.uri("http://foo.bar.com")]])
- return wide_data
-_wide_array_bench_data = build_wide_array_xml()
-
-def bench_stream(parse, stream):
- ret = parse(stream)
- stream.seek(0)
- return ret
-
-
-def test_parse_xml_stream(benchmark, xml_stream):
- ret = benchmark(bench_stream, llsd.parse_xml, xml_stream)
- assertDictEqual(ret, _bench_data)
-
-
-def test_parse_notation_stream(benchmark, notation_stream):
- ret = benchmark(bench_stream, llsd.parse_notation, notation_stream)
- assertDictEqual(ret, _bench_data)
-
-
-def test_parse_binary_stream(benchmark, binary_stream):
- ret = benchmark(bench_stream, llsd.parse_binary, binary_stream)
- assertDictEqual(ret, _bench_data)
-
-
-def test_parse_notation_bytes(benchmark):
- ret = benchmark(llsd.parse_notation, BENCH_DATA_NOTATION)
- assertDictEqual(ret, _bench_data)
-
-
-def test_parse_xml_bytes(benchmark):
- res = benchmark(llsd.parse_xml, BENCH_DATA_XML)
- assertDictEqual(res, _bench_data)
-
-
-def test_parse_binary_bytes(benchmark):
- res = benchmark(llsd.parse_binary, BENCH_DATA_BINARY)
- assertDictEqual(res, _bench_data)
-
-
-def test_format_xml(benchmark):
- benchmark(llsd.format_xml, _bench_data)
-
-
-def test_format_notation(benchmark):
- benchmark(llsd.format_notation, _bench_data)
-
-
-def test_format_binary(benchmark):
- benchmark(llsd.format_binary, _bench_data)
-
-def test_format_xml_deep(benchmark):
- benchmark(llsd.format_xml, _deep_bench_data)
-
-def test_format_xml_wide(benchmark):
- benchmark(llsd.format_xml, _wide_bench_data)
-
-def test_format_notation_deep(benchmark):
- benchmark(llsd.format_notation, _deep_bench_data)
-
-def test_format_notation_wide(benchmark):
- benchmark(llsd.format_notation, _wide_bench_data)
-
-def test_format_notation_wide_array(benchmark):
- benchmark(llsd.format_notation, _wide_array_bench_data)
-
-def test_format_binary_deep(benchmark):
- benchmark(llsd.format_binary, _deep_bench_data)
-
-def test_format_binary_wide(benchmark):
- benchmark(llsd.format_binary, _wide_bench_data)
-
-def test_format_binary_wide_array(benchmark):
- benchmark(llsd.format_binary, _wide_array_bench_data)
-
-def test_parse_xml_deep(benchmark):
- deep_data = llsd.format_xml(_deep_bench_data)
- benchmark(llsd.parse_xml, deep_data)
-
-def test_parse_binary_deep(benchmark):
- deep_data = llsd.format_binary(_deep_bench_data)
- benchmark(llsd.parse_binary, deep_data)
diff --git a/tests/fixtures/viewer-autobuild.xml b/tests/fixtures/viewer-autobuild.xml
deleted file mode 100644
index 2e4397a..0000000
--- a/tests/fixtures/viewer-autobuild.xml
+++ /dev/null
@@ -1,3977 +0,0 @@
-
-
-
- installables
-
- SDL
-
- copyright
- Copyright (C) 1997-2012 Sam Lantinga
- description
- Simple DirectMedia Layer is a cross-platform multimedia library designed to provide low level access to audio, keyboard, mouse, joystick, 3D hardware via OpenGL, and 2D video framebuffer.
- license
- lgpl
- license_file
- LICENSES/SDL.txt
- name
- SDL
- platforms
-
- linux
-
- archive
-
- hash
- 459cdc8d7c19a8025f98f61db95622ff
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/sdl_3p-update-sdl/rev/297546/arch/Linux/installer/SDL-1.2.15-linux-297546.tar.bz2
-
- name
- linux
-
- linux64
-
- archive
-
- hash
- 7ea2df03bfc35c06acf23dd9e734adac
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1103/2554/SDL-1.2.15-linux64-501092.tar.bz2
-
- name
- linux64
-
-
- version
- 1.2.15
-
- apr_suite
-
- copyright
- Copyright Β© 2012 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.
- description
- Apache portable runtime project
- license
- apache
- license_file
- LICENSES/apr_suite.txt
- name
- apr_suite
- platforms
-
- darwin
-
- archive
-
- hash
- 0c53148aa00e51c06fa246c4130915be
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/apr_3p-update-apr/rev/297252/arch/Darwin/installer/apr_suite-1.4.5.297252-darwin-297252.tar.bz2
-
- name
- darwin
-
- darwin64
-
- archive
-
- hash
- b6357ef3a0ec37877a5831820f25094e
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/80557/759704/apr_suite-1.4.5.558565-darwin64-558565.tar.bz2
-
- name
- darwin64
-
- linux
-
- archive
-
- hash
- 1aa2e5355bb9df09f9196d14a72b6705
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-apr/rev/314241/arch/Linux/installer/apr_suite-1.4.5.314241-linux-314241.tar.bz2
-
- name
- linux
-
- linux64
-
- archive
-
- hash
- 84a1a140f20b25d714949185e854d14b
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/4811/15302/apr_suite-1.4.5.504800-linux64-504800.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- cb48ac069440f6dcd564cfa9fd02a4c2
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/80556/759710/apr_suite-1.4.5.558565-windows-558565.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- 646dc3828d9c39fb1e77c4eec44ed739
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/80555/759709/apr_suite-1.4.5.558565-windows64-558565.tar.bz2
-
- name
- windows64
-
-
- version
- 1.4.5.558565
-
- boost
-
- copyright
- (see individual source files)
- description
- Boost C++ Libraries
- license
- boost 1.0
- license_file
- LICENSES/boost.txt
- name
- boost
- platforms
-
- darwin
-
- archive
-
- hash
- c296845cad075250c1ae2620f175a957
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/boost_3p-update-boost/rev/297445/arch/Darwin/installer/boost-1.57-darwin-297445.tar.bz2
-
- name
- darwin
-
- darwin64
-
- archive
-
- hash
- 35cc090d942b85c9126ceac9912d52d6
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78585/744021/boost-1.72-darwin64-557045.tar.bz2
-
- name
- darwin64
-
- linux
-
- archive
-
- hash
- f1fdb548fd6c09a083c86f3a23d7f041
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-boost/rev/317807/arch/Linux/installer/boost-1.57-linux-317807.tar.bz2
-
- name
- linux
-
- linux64
-
- archive
-
- hash
- 038853b97307a9b65de20c4c50098023
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/9675/45694/boost-1.65.1-linux64-509640.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- 9aa4ce32df5f5e36124c990e2d77b885
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78586/743982/boost-1.72-windows-557045.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- a79511c9d8b956767ebaa405155d4238
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78584/743961/boost-1.72-windows64-557045.tar.bz2
-
- name
- windows64
-
-
- version
- 1.72
-
- bugsplat
-
- copyright
- Copyright 2003-2017, BugSplat
- description
- Bugsplat crash reporting package
- license
- Proprietary
- license_file
- LICENSES/BUGSPLAT_LICENSE.txt
- name
- bugsplat
- platforms
-
- darwin64
-
- archive
-
- hash
- ae90d19cdcddf539f6d0b41cab12f918
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/72773/702861/bugsplat-1.0.7.552580-darwin64-552580.tar.bz2
-
- name
- darwin64
-
- windows
-
- archive
-
- hash
- f5936eceb6a33ff0f1cc31996a40f29c
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/72774/702905/bugsplat-3.6.0.8.552580-windows-552580.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- 9cd940754e53e0670030b3da5ba8f373
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/72775/702906/bugsplat-3.6.0.8.552580-windows64-552580.tar.bz2
-
- name
- windows64
-
-
- version
- 3.6.0.8.552580
-
- colladadom
-
- copyright
- Copyright 2006 Sony Computer Entertainment Inc.
- license
- SCEA
- license_file
- LICENSES/collada.txt
- name
- colladadom
- platforms
-
- darwin
-
- archive
-
- hash
- 726bc31e562752f081e95e8fcc70e405
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/colladadom_3p-update-colladadom/rev/297450/arch/Darwin/installer/colladadom-2.3.297450-darwin-297450.tar.bz2
-
- name
- darwin
-
- darwin64
-
- archive
-
- hash
- 1d063cf1783e7788f17486c234adb1db
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78635/744249/colladadom-2.3.557064-darwin64-557064.tar.bz2
-
- name
- darwin64
-
- linux
-
- archive
-
- hash
- 78b9a6506fb7d53da166f7a65f2278f4
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-colladadom/rev/317826/arch/Linux/installer/colladadom-2.3.317826-linux-317826.tar.bz2
-
- name
- linux
-
- linux64
-
- archive
-
- hash
- c90613240ba3e3a171d3379275ae4ee3
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/9695/45732/colladadom-2.3.509683-linux64-509683.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- e78ecf919eee01567556787c3a358d15
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78637/744269/colladadom-2.3.557064-windows-557064.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- 7e63a212c8909a25236138422fe01298
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78636/744273/colladadom-2.3.557064-windows64-557064.tar.bz2
-
- name
- windows64
-
-
- version
- 2.3.557064
-
- curl
-
- copyright
- Copyright (c) 1996 - 2014, Daniel Stenberg, (daniel@haxx.se).
- description
- Library for transferring data specified with URL syntax
- license
- curl
- license_file
- LICENSES/curl.txt
- name
- curl
- platforms
-
- darwin
-
- archive
-
- hash
- ad0061db7188a1b9a974eb0512eeeb8d
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-curl/rev/312763/arch/Darwin/installer/curl-7.47.0.312763-darwin-312763.tar.bz2
-
- name
- darwin
-
- darwin64
-
- archive
-
- hash
- 13f74f43a6363ec998569f731fd869c5
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/82637/774617/curl-7.54.1.560191-darwin64-560191.tar.bz2
-
- name
- darwin64
-
- linux
-
- archive
-
- hash
- 9430c08954c00736117099046694e1b1
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-curl/rev/314230/arch/Linux/installer/curl-7.47.0.314230-linux-314230.tar.bz2
-
- name
- linux
-
- linux64
-
- archive
-
- hash
- 630a2ddf43bba6e5b6e171dc68921dcb
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/8663/36142/curl-7.54.1.508652-linux64-508652.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- 0df99bd685dc3561ca8ea347b2921987
- hash_algorithm
- md5
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/82639/774610/curl-7.54.1.560191-windows-560191.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- 50db2a9e6b74ec4b0c38b1ea8f135735
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/82638/774608/curl-7.54.1.560191-windows64-560191.tar.bz2
-
- name
- windows64
-
-
- version
- 7.54.1.560191
-
- db
-
- copyright
- Copyright (c) 1990, 2010 Oracle and/or its affiliates. All rights reserved.
- description
- Berkeley DB (libdb) is a programmatic toolkit that provides embedded database support for both traditional and client/server applications.
- license
- bsd
- license_file
- LICENSES/db.txt
- name
- db
- platforms
-
- linux
-
- archive
-
- hash
- 1cc7940e500858a9754e9a3cc3ba2237
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/db_3p-update-db/rev/295315/arch/Linux/installer/db-5.1.25-linux-295315.tar.bz2
-
- name
- linux
-
-
- version
- 5.1.25
-
- dbus_glib
-
- copyright
- Copyright (C) Red Hat Inc.
- description
- D-Bus bindings for glib
- license
- Academic Free License v. 2.1
- license_file
- LICENSES/dbus-glib.txt
- name
- dbus_glib
- platforms
-
- linux
-
- archive
-
- hash
- 6d676abd9ad8d2883b855dbe397d9034
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-dbus-glib/rev/314266/arch/Linux/installer/dbus_glib-0.76-linux-314266.tar.bz2
-
- name
- linux
-
- linux64
-
- archive
-
- hash
- 7ee7b9aed3c0c8c09e7bf26bba7af8e1
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-dbus-glib/rev/314266/arch/Linux/installer/dbus_glib-0.76-linux64-314266.tar.bz2
-
- name
- linux64
-
-
- version
- 0.76
-
- dictionaries
-
- copyright
- Copyright 2014 Apache OpenOffice software
- description
- Spell checking dictionaries to bundled into the viewer
- license
- various open source
- license_file
- LICENSES/dictionaries.txt
- name
- dictionaries
- platforms
-
- common
-
- archive
-
- hash
- d778c6a3475bc35ee8b9615dfc38b4a9
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/55025/511964/dictionaries-1.538984-common-538984.tar.bz2
-
- name
- common
-
-
- version
- 1.538984
-
- dullahan
-
- copyright
- Copyright (c) 2017, Linden Research, Inc.
- description
- A headless browser SDK that uses the Chromium Embedded Framework (CEF). It is designed to make it easier to write applications that render modern web content directly to a memory buffer, inject synthesized mouse and keyboard events as well as interact with web based features like JavaScript or cookies.
- license
- MPL
- license_file
- LICENSES/LICENSE.txt
- name
- dullahan
- platforms
-
- darwin64
-
- archive
-
- hash
- 45dedb5b09995cd794304150e94fcf21
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/87950/806969/dullahan-1.12.2.202109170444_91.1.21_g9dd45fe_chromium-91.0.4472.114-darwin64-563968.tar.bz2
-
- name
- darwin64
-
- windows
-
- archive
-
- hash
- d0fd9d7086699da4bb5ccc935622a717
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/88276/809277/dullahan-1.12.2.202109230751_91.1.21_g9dd45fe_chromium-91.0.4472.114-windows-563968.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- 7e8c3ccd420ff5aef24ff72d609ba394
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/88275/809281/dullahan-1.12.2.202109230751_91.1.21_g9dd45fe_chromium-91.0.4472.114-windows64-563968.tar.bz2
-
- name
- windows64
-
-
- version
- 1.12.2.202109230751_91.1.21_g9dd45fe_chromium-91.0.4472.114
-
- elfio
-
- license
- lgpl
- license_file
- LICENSES/elfio.txt
- name
- elfio
- platforms
-
- linux
-
- archive
-
- hash
- 031e6315a5c0829c9b9a2ec18aeb7ae3
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-elfio/rev/222074/arch/Linux/installer/elfio-1.0.3-linux-20110225.tar.bz2
-
- name
- linux
-
-
-
- expat
-
- copyright
- Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd and Clark Cooper - Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Expat maintainers.
- description
- Expat is an XML parser library written in C
- license
- expat
- license_file
- LICENSES/expat.txt
- name
- expat
- platforms
-
- darwin
-
- archive
-
- hash
- 452d1910ef853329cd59858e6c5b2c48
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/expat_3p-update-expat/rev/297014/arch/Darwin/installer/expat-2.0.1.297014-darwin-297014.tar.bz2
-
- name
- darwin
-
- darwin64
-
- archive
-
- hash
- f4e80e0dfcab713a3da90cd8f7f23e7b
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76341/727265/expat-2.1.1.555519-darwin64-555519.tar.bz2
-
- name
- darwin64
-
- linux
-
- archive
-
- hash
- 387c90b9bb5ec412587fbe7a56261dd1
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-expat/rev/314211/arch/Linux/installer/expat-2.1.1.314211-linux-314211.tar.bz2
-
- name
- linux
-
- linux64
-
- archive
-
- hash
- 5e1f025d1cebd12db542080aa755257f
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/380/943/expat-2.1.1.500375-linux64-500375.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- cd4fe03473076c324d80ae3bd91a85bb
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76343/727273/expat-2.1.1.555519-windows-555519.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- d2d74d73b914150982b1883a3b96e60b
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76344/727279/expat-2.1.1.555519-windows64-555519.tar.bz2
-
- name
- windows64
-
-
- version
- 2.1.1.555519
-
- fmodstudio
-
- copyright
- FMOD Studio by Firelight Technologies Pty Ltd.
- description
- FMOD Studio API
- license
- fmod
- license_file
- LICENSES/fmodstudio.txt
- name
- fmodstudio
- platforms
-
- darwin64
-
- archive
-
- hash
- d5528538e67c710387ae0c061a90cb23
- url
- https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/76868/730756/fmodstudio-2.01.07.555883-darwin64-555883.tar.bz2
-
- name
- darwin64
-
- linux
-
- archive
-
- hash
- 5283050c22d31877cd9e0afbe6feb9fc
- url
- http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/65398/612630/fmodstudio-2.00.11.546392-linux-546392.tar.bz2
-
- name
- linux
-
- linux64
-
- archive
-
- hash
- 5a3c78f4a77ae6477986e33836725e8b
- url
- http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/65399/612631/fmodstudio-2.00.11.546392-linux64-546392.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- a2bb6eaf51f933993b26a5fe7503a761
- url
- https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/76869/730763/fmodstudio-2.01.07.555883-windows-555883.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- 138d07dd516a9ad5b9787192fe6134dd
- url
- https://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/76867/730751/fmodstudio-2.01.07.555883-windows64-555883.tar.bz2
-
- name
- windows64
-
-
- version
- 2.01.07.555883
-
- fontconfig
-
- copyright
- Copyright (C) 2000,2001,2002,2003,2004,2006,2007 Keith Packard, 2005 Patrick Lam, 2009 Roozbeh Pournader, 2008,2009 Red Hat, Inc., 2008 Danilo Ε egan, 2012 Google, Inc.
- description
- Fontconfig is a library for configuring and customizing font access.
- license
- bsd
- license_file
- LICENSES/fontconfig.txt
- name
- fontconfig
- platforms
-
- linux
-
- archive
-
- hash
- a20a3d0ab7fc3401bc2ca81e9309f630
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-fontconfig/rev/314281/arch/Linux/installer/fontconfig-2.11.0-linux-314281.tar.bz2
-
- name
- linux
-
- linux64
-
- archive
-
- hash
- e2419d56960c160670051fbb055fb729
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-fontconfig/rev/314281/arch/Linux/installer/fontconfig-2.11.0-linux64-314281.tar.bz2
-
- name
- linux64
-
-
- version
- 2.11.0
-
- freetype
-
- copyright
- Copyright 2006, 2007, 2008, 2009, 2010 by David Turner, Robert Wilhelm, and Werner Lemberg.
- description
- Font rendering library
- license
- FreeType
- license_file
- LICENSES/freetype.txt
- name
- freetype
- platforms
-
- darwin
-
- archive
-
- hash
- 83618d16d974eb0af93926a10ac13297
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/freetype_3p-update-freetype/rev/297053/arch/Darwin/installer/freetype-2.4.4.297053-darwin-297053.tar.bz2
-
- name
- darwin
-
- darwin64
-
- archive
-
- hash
- 3a478d6c8a10d49d9161ef864394b03c
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78592/744013/freetype-2.4.4.557047-darwin64-557047.tar.bz2
-
- name
- darwin64
-
- linux
-
- archive
-
- hash
- 1b401394106cedc86926bd488f5aa45e
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-freetype/rev/314215/arch/Linux/installer/freetype-2.4.4.314215-linux-314215.tar.bz2
-
- name
- linux
-
- linux64
-
- archive
-
- hash
- 94cf61dfdbc86aae5bbaf0b5cb8a366c
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/874/1914/freetype-2.4.4.500865-linux64-500865.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- 7ee200d6b5fa282c7f973ade5615aa86
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78594/744011/freetype-2.4.4.557047-windows-557047.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- 69307aaba16ac71531c9c4d930ace993
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78593/744010/freetype-2.4.4.557047-windows64-557047.tar.bz2
-
- name
- windows64
-
-
- version
- 2.4.4.557047
-
- glext
-
- copyright
- Copyright (c) 2007-2010 The Khronos Group Inc.
- description
- glext headers define function prototypes and constants for OpenGL extensions
- license
- Copyright (c) 2007-2010 The Khronos Group Inc.
- license_file
- LICENSES/glext.txt
- name
- glext
- platforms
-
- darwin64
-
- archive
-
- hash
- 1bd3214ac23474ea4c869e386970a1be
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54835/510029/glext-68-darwin64-538965.tar.bz2
-
- name
- darwin64
-
- linux
-
- archive
-
- hash
- baf1fd13e1fe6aef586200fc87a70f53
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-glext/rev/314200/arch/Linux/installer/glext-68-linux-314200.tar.bz2
-
- name
- linux
-
- linux64
-
- archive
-
- hash
- 5f3c9d61b620f949b199ebd8885218ed
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-glext/rev/314200/arch/Linux/installer/glext-68-linux64-314200.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- 6a311615bce59b01cf73ee65012a9b38
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54951/511711/glext-68-windows-538965.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- daf619dab1cf7518af6532b18800c4b0
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54924/511490/glext-68-windows64-538965.tar.bz2
-
- name
- windows64
-
-
- version
- 68
-
- glh_linear
-
- copyright
- Copyright (c) 2000 Cass Everitt
- description
- glh - is a platform-indepenedent C++ OpenGL helper library
- license
- BSD
- license_file
- LICENSES/glh-linear.txt
- name
- glh_linear
- platforms
-
- common
-
- archive
-
- hash
- 650e836255b6c2ecb93d3f1f7220051c
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/55011/511905/glh_linear-0.0.0-common-538981.tar.bz2
-
- name
- common
-
-
- version
- 0.0.0
-
- glod
-
- copyright
- Copyright 2003 Jonathan Cohen, Nat Duca, David Luebke, Brenden Schubert - Johns Hopkins University and University of Virginia
- license
- GLOD Open-Source License Version 1.0
- license_file
- LICENSES/GLOD.txt
- name
- glod
- platforms
-
- darwin
-
- archive
-
- hash
- 71e678d70e276fc42a56926fc28a7abd
- hash_algorithm
- md5
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/glod_3p-update-glod/rev/296895/arch/Darwin/installer/glod-1.0pre4.296895-darwin-296895.tar.bz2
-
- name
- darwin
-
- darwin64
-
- archive
-
- hash
- a9eaa005ff9d387f946283fbcb69b3c8
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76353/727324/glod-1.0pre3.555522-darwin64-555522.tar.bz2
-
- name
- darwin64
-
- linux
-
- archive
-
- hash
- 58113bcbbacbaeb2d278f745867ae6f0
- hash_algorithm
- md5
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-glod/rev/314201/arch/Linux/installer/glod-1.0pre4.314201-linux-314201.tar.bz2
-
- name
- linux
-
- linux64
-
- archive
-
- hash
- 9aef5cd576ace19568da01d9bc3db29c
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1625/3628/glod-1.0pre3.501614-linux64-501614.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- e36c95b0d0fbaa3ff3392facaf5de447
- hash_algorithm
- md5
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/55008/511893/glod-1.0pre3.538980-windows-538980.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- 6302ee1903ab419e76565d9eb6acd274
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/55004/511885/glod-1.0pre3.538980-windows64-538980.tar.bz2
-
- name
- windows64
-
-
- version
- 1.0pre3.555522
-
- googlemock
-
- copyright
- Copyright 2008, Google Inc.
- description
- a library for writing and using C++ mock classes
- license
- BSD
- license_file
- LICENSES/gmock.txt
- name
- googlemock
- platforms
-
- darwin
-
- archive
-
- hash
- 022649e284163b8ee23e3c9a81302fa7
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/googlemock_3p-update-googlemock/rev/297460/arch/Darwin/installer/googlemock-1.7.0.297460-darwin-297460.tar.bz2
-
- name
- darwin
-
- darwin64
-
- archive
-
- hash
- 19e925604bc1a91efb4b130e1edd8bf2
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78620/744140/googlemock-1.7.0.557057-darwin64-557057.tar.bz2
-
- name
- darwin64
-
- linux
-
- archive
-
- hash
- ad51f68702f25ba245fff312c50c8876
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-googlemock/rev/317828/arch/Linux/installer/googlemock-1.7.0.317828-linux-317828.tar.bz2
-
- name
- linux
-
- linux64
-
- archive
-
- hash
- ff459b58695c76838782847a0b792104
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/9697/45717/googlemock-1.7.0.509686-linux64-509686.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- eed7b41d0d1f41b24f315349ef78c728
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78622/744148/googlemock-1.7.0.557057-windows-557057.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- a6ad6fe722d2fe4e8137495af3f374c9
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78621/744152/googlemock-1.7.0.557057-windows64-557057.tar.bz2
-
- name
- windows64
-
-
- version
- 1.7.0.557057
-
- gstreamer
-
- copyright
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
- license
- LGPL
- license_file
- LICENSES/gstreamer.txt
- name
- gstreamer
- platforms
-
- linux
-
- archive
-
- hash
- 5017b3e95d2c6f47bb111c3f9c075522
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-gstreamer/rev/314267/arch/Linux/installer/gstreamer-0.10.6.314267-linux-314267.tar.bz2
-
- name
- linux
-
- linux64
-
- archive
-
- hash
- 7c9d7cc88add7831a6afeedc20cad2fe
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-gstreamer/rev/314267/arch/Linux/installer/gstreamer-0.10.6.314267-linux64-314267.tar.bz2
-
- name
- linux64
-
-
- version
- 0.10.6.314267
-
- gtk-atk-pango-glib
-
- copyright
- Copyright (various, see sources)
- license
- lgpl
- license_file
- LICENSES/gtk-atk-pango-glib.txt
- name
- gtk-atk-pango-glib
- platforms
-
- linux
-
- archive
-
- hash
- a6431df705526501684d9050e04bfa5b
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-gtk-atk-pango-glib/rev/314220/arch/Linux/installer/gtk_atk_pango_glib-0.1-linux-314220.tar.bz2
-
- name
- linux
-
- linux64
-
- archive
-
- hash
- de7bba8fd2275a11b077b124413065d0
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-gtk-atk-pango-glib/rev/314220/arch/Linux/installer/gtk_atk_pango_glib-0.1-linux64-314220.tar.bz2
-
- name
- linux64
-
-
- version
- 0.1
-
- havok-source
-
- copyright
- Uses Havok (TM) Physics. (c)Copyright 1999-2010 Havok.com Inc. (and its Licensors). All Rights Reserved. See www.havok.com for details.
- description
- Havok source code for libs and demos
- license
- havok
- license_file
- LICENSES/havok.txt
- name
- havok-source
- platforms
-
- darwin
-
- archive
-
- hash
- 5c5b4820999ae9e398801d6a46f45897
- url
- http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/havok-source_3p-update-havok-source/rev/297312/arch/Darwin/installer/havok_source-2012.1-darwin-297312.tar.bz2
-
- name
- darwin
-
- darwin64
-
- archive
-
- hash
- ba229348c1d9d58519cd854ff9d8ef3d
- url
- http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/55213/512968/havok_source-2012.1-2-darwin64-539117.tar.bz2
-
- name
- darwin64
-
- linux
-
- archive
-
- hash
- 03c1c5f7c3e93e905f635ca22b607494
- url
- http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/p64_3p-havok-source/rev/314226/arch/Linux/installer/havok_source-2012.1-2-linux-314226.tar.bz2
-
- name
- linux
-
- linux64
-
- archive
-
- hash
- 00d0333936a67059a43a6ec8ac38d564
- url
- http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/748/1563/havok_source-2012.1-2-linux64-500739.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- 4ff2af85106907acb171bb1e38a3757e
- url
- http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/55214/512993/havok_source-2012.1-2-windows-539117.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- bcaf4631ea10f7d09eecb73e8f5bef6c
- url
- http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/55212/512962/havok_source-2012.1-2-windows64-539117.tar.bz2
-
- name
- windows64
-
-
- version
- 2012.1-2
-
- jpeglib
-
- copyright
- Copyright (C) 1991-2011, Thomas G. Lane, Guido Vollbeding.
- description
- JPEG encoding, decoding library
- license
- jpeglib
- license_file
- LICENSES/jpeglib.txt
- name
- jpeglib
- platforms
-
- darwin
-
- archive
-
- hash
- 4d7658997fd0f93a9c55e40e40b1b0e5
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/jpeglib_3p-update-jpeglib/rev/296854/arch/Darwin/installer/jpeglib-8c.296854-darwin-296854.tar.bz2
-
- name
- darwin
-
- darwin64
-
- archive
-
- hash
- 3f2e34e3a2dac8eea957cad143a71dc5
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54847/510113/jpeglib-8c.538977-darwin64-538977.tar.bz2
-
- name
- darwin64
-
- linux
-
- archive
-
- hash
- 32560d3200da72fea2922371fcef25f5
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-jpeglib/rev/314202/arch/Linux/installer/jpeglib-8c.314202-linux-314202.tar.bz2
-
- name
- linux
-
- linux64
-
- archive
-
- hash
- ba9c62863ec338a049de83c24639f57c
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/3151/7568/jpeglib-8c.503140-linux64-503140.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- c8dee00ef13af40ec68becc25830e195
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54992/511854/jpeglib-8c.538977-windows-538977.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- 6f40620e86f3c9b91b6b5fe3c81776fc
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54991/511847/jpeglib-8c.538977-windows64-538977.tar.bz2
-
- name
- windows64
-
-
- version
- 8c.538977
-
- jsoncpp
-
- copyright
- Copyright (c) 2007-2010 Baptiste Lepilleur
- description
- jsoncpp is an implementation of a JSON (http://json.org) reader and writer in C++.
- license
- public domain
- license_file
- LICENSES/jsoncpp.txt
- name
- jsoncpp
- platforms
-
- darwin
-
- archive
-
- hash
- b25a4f480e07c670ffef00c3da578f87
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/jsoncpp_3p-update-jsoncpp/rev/297281/arch/Darwin/installer/jsoncpp-0.5.0.297281-darwin-297281.tar.bz2
-
- name
- darwin
-
- darwin64
-
- archive
-
- hash
- 87d32aaac4183590c96edd0b6d9bf3e4
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54846/510106/jsoncpp-0.5.0.538976-darwin64-538976.tar.bz2
-
- name
- darwin64
-
- linux
-
- archive
-
- hash
- 9d5d9fec28cbbb1651b95728173f8af7
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-jsoncpp/rev/314229/arch/Linux/installer/jsoncpp-0.5.0.314229-linux-314229.tar.bz2
-
- name
- linux
-
- linux64
-
- archive
-
- hash
- 9a658ae561c75e60bd9c0cee56731d21
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1475/3274/jsoncpp-0.5.0.501464-linux64-501464.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- b73d9addab278eacc100bd312ab6ec5c
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54990/511840/jsoncpp-0.5.0.538976-windows-538976.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- 1b9ac5708cc526d2c5358ef0a427109d
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54989/511833/jsoncpp-0.5.0.538976-windows64-538976.tar.bz2
-
- name
- windows64
-
-
- version
- 0.5.0.538976
-
- kdu
-
- copyright
- Kakadu software
- description
- JPEG2000 library by Kakadu
- license
- Kakadu
- license_file
- LICENSES/kdu.txt
- name
- kdu
- platforms
-
- darwin
-
- archive
-
- hash
- 3855bd40f950e3c22739ae8f3ee2afc9
- url
- http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/15258/98444/kdu-7.10.4.513518-darwin-513518.tar.bz2
-
- name
- darwin
-
- darwin64
-
- archive
-
- hash
- ccfd8eacd1ebe92715944094064ba2e4
- url
- http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/55187/512570/kdu-7.10.4.539108-darwin64-539108.tar.bz2
-
- name
- darwin64
-
- linux
-
- archive
-
- hash
- 43d7a6a69a54534a736f132e9c81795b
- url
- http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/15255/98451/kdu-7.10.4.513518-linux-513518.tar.bz2
-
- name
- linux
-
- linux64
-
- archive
-
- hash
- a705a665810a71e7b0114a97ae9a2224
- url
- http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/15256/98457/kdu-7.10.4.513518-linux64-513518.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- 38574fbcb6c94c42745ef48748002e58
- url
- http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/55189/512583/kdu-7.10.4.539108-windows-539108.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- 3dfeb869c781a766874f0aedc7d4fcef
- url
- http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/55188/512576/kdu-7.10.4.539108-windows64-539108.tar.bz2
-
- name
- windows64
-
-
- version
- 7.10.4.539108
-
- libhunspell
-
- copyright
- See hunspell.txt
- description
- Spell checking library
- license
- LGPL
- license_file
- LICENSES/hunspell.txt
- name
- libhunspell
- platforms
-
- darwin
-
- archive
-
- hash
- 05eda16106df26a211f8bdd874d1fca5
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/hunspell_3p-update-hunspell/rev/296916/arch/Darwin/installer/libhunspell-1.3.2.296916-darwin-296916.tar.bz2
-
- name
- darwin
-
- darwin64
-
- archive
-
- hash
- 2021ea3a19b81c82993e733709683303
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76371/727419/libhunspell-1.3.2.555528-darwin64-555528.tar.bz2
-
- name
- darwin64
-
- linux
-
- archive
-
- hash
- 0d8009c3b6c1eb510593476dd1d821b5
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-hunspell/rev/314217/arch/Linux/installer/libhunspell-1.3.2.314217-linux-314217.tar.bz2
-
- name
- linux
-
- linux64
-
- archive
-
- hash
- ffbdd109356d66ddfefd8a5d57f63f1f
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/533/1144/libhunspell-1.3.2.500526-linux64-500526.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- 2253ec09136cc7c208481030d78d9dd7
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76369/727412/libhunspell-1.3.2.555528-windows-555528.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- 858d1708f6b3a74738a3d57a5387e20f
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76370/727413/libhunspell-1.3.2.555528-windows64-555528.tar.bz2
-
- name
- windows64
-
-
- version
- 1.3.2.555528
-
- libndofdev
-
- copyright
- Copyright (c) 2007, 3Dconnexion, Inc. - All rights reserved.
- description
- 3DConnexion SDK
- license
- BSD
- license_file
- LICENSES/libndofdev.txt
- name
- libndofdev
- platforms
-
- darwin
-
- archive
-
- hash
- a01b411433dbf8a4b481de9e76d9a652
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/libndofdev_3p-update-libndofdev/rev/297264/arch/Darwin/installer/libndofdev-0.1.297264-darwin-297264.tar.bz2
-
- name
- darwin
-
- darwin64
-
- archive
-
- hash
- a487fff84208a45844602c4a1f68c974
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76356/727333/libndofdev-0.1.555523-darwin64-555523.tar.bz2
-
- name
- darwin64
-
- windows
-
- archive
-
- hash
- 4c839555bf0ed9ae60ffc3f8a7c96f9b
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76354/727340/libndofdev-0.1.555523-windows-555523.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- cbc033ae3b034b992b59f6de1034247c
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76355/727341/libndofdev-0.1.555523-windows64-555523.tar.bz2
-
- name
- windows64
-
-
- version
- 0.1.555523
-
- libpng
-
- copyright
- Copyright (c) 2004, 2006-2013 Glenn Randers-Pehrson
- description
- PNG Reference library
- license
- libpng
- license_file
- LICENSES/libpng.txt
- name
- libpng
- platforms
-
- darwin
-
- archive
-
- hash
- 14cb5c8686a472e9e60179e46cd196f7
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/libpng_3p-update-libpng/rev/297708/arch/Darwin/installer/libpng-1.6.8.297708-darwin-297708.tar.bz2
-
- name
- darwin
-
- darwin64
-
- archive
-
- hash
- 2a41acc3116ce19a443873216cb882ad
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78587/743948/libpng-1.6.8.557046-darwin64-557046.tar.bz2
-
- name
- darwin64
-
- linux
-
- archive
-
- hash
- 0758f3cb4c02ebab61854b811b0894e9
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-libpng/rev/314214/arch/Linux/installer/libpng-1.6.8.314214-linux-314214.tar.bz2
-
- name
- linux
-
- linux64
-
- archive
-
- hash
- 13de93ea11544051b69f238eeb644fd3
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/882/1946/libpng-1.6.8.500873-linux64-500873.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- b935b440947f63c69700bdcf5095a8e1
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78591/743970/libpng-1.6.8.557046-windows-557046.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- d1cc8354ac4e877eefedf16b1be3aac6
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78589/743991/libpng-1.6.8.557046-windows64-557046.tar.bz2
-
- name
- windows64
-
-
- version
- 1.6.8.557046
-
- libuuid
-
- copyright
- Copyright (c) 2004-2008 The OSSP Project <http://www.ossp.org/>
- description
- OSSP uuid is a ISO-C:1999 application programming interface (API) and corresponding command line interface (CLI) for the generation of DCE 1.1, ISO/IEC 11578:1996 and RFC 4122 compliant Universally Unique Identifier (UUID).
- license
- UUID
- license_file
- LICENSES/uuid.txt
- name
- libuuid
- platforms
-
- linux
-
- archive
-
- hash
- a2eaf9515cd129f3e21a08e92689006b
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-libuuid/rev/314269/arch/Linux/installer/libuuid-1.6.2-linux-314269.tar.bz2
-
- name
- linux
-
- linux64
-
- archive
-
- hash
- fb89f1281dd54d8b99b339fc5b712b27
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-libuuid/rev/314269/arch/Linux/installer/libuuid-1.6.2-linux64-314269.tar.bz2
-
- name
- linux64
-
-
- version
- 1.6.2
-
- libxml2
-
- copyright
- Copyright (C) 1998-2012 Daniel Veillard. All Rights Reserved.
- description
- Libxml2 is the XML C parser and toolkit developed for the Gnome project.
- license
- mit
- license_file
- LICENSES/libxml2.txt
- name
- libxml2
- platforms
-
- darwin
-
- archive
-
- hash
- 9303f0dd174129e297eca6cc2eb1ab3f
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/libxml_3p-update-libxml/rev/297050/arch/Darwin/installer/libxml2-2.9.1.297050-darwin-297050.tar.bz2
-
- name
- darwin
-
- darwin64
-
- archive
-
- hash
- 6677173bbbb0ea32369b5e9b6c9aa641
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78631/744225/libxml2-2.9.4.557062-darwin64-557062.tar.bz2
-
- name
- darwin64
-
- linux
-
- archive
-
- hash
- 6954173a141d928f2614076577d952de
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-libxml/rev/314197/arch/Linux/installer/libxml2-2.9.1.314197-linux-314197.tar.bz2
-
- name
- linux
-
- linux64
-
- archive
-
- hash
- 740fc93f195c77b3a0c0800b31878ecb
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/890/1968/libxml2-2.9.4.500877-linux64-500877.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- ad6a596fbf0e83a21d95762da78437bc
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78633/744239/libxml2-2.9.4.557062-windows-557062.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- 6b5bb230684ecf28386d7c91c47bb6e1
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78634/744240/libxml2-2.9.4.557062-windows64-557062.tar.bz2
-
- name
- windows64
-
-
- version
- 2.9.4.557062
-
- llappearance_utility
-
- copyright
- Copyright (c) 2000-2012, Linden Research, Inc.
- description
- Linden Lab appearance utility for server-side avatar baking services.
- license
- Proprietary
- license_file
- LICENSES/llappearanceutility.txt
- name
- llappearance_utility
- platforms
-
- linux
-
- archive
-
- hash
- fddd634dec5ec03924d62cc774f7f8ea
- url
- http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/p64_viewer-llappearance-utility/rev/317266/arch/Linux/installer/llappearance_utility-0.0.1-linux-317266.tar.bz2
-
- name
- linux
-
-
- version
- 0.0.1
-
- llca
-
- copyright
- Copyright (c) 2016, Linden Research, Inc.; data provided by the Mozilla NSS Project.
-
- license
- mit
- license_file
- LICENSES/ca-license.txt
- name
- llca
- platforms
-
- common
-
- archive
-
- hash
- 0a6349b11c8e9d34f0c80b8081736e75
- hash_algorithm
- md5
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/79438/751815/llca-202104010215.557744-common-557744.tar.bz2
-
- name
- common
-
-
- version
- 202104010215.557744
-
- llphysicsextensions_source
-
- copyright
- Copyright (c) 2010, Linden Research, Inc.
- license
- internal
- license_file
- LICENSES/llphysicsextensions.txt
- name
- llphysicsextensions_source
- platforms
-
- darwin64
-
- archive
-
- hash
- 14fac452271ebfba37ba5ddcf5bffa54
- url
- http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/54842/510078/llphysicsextensions_source-1.0.538972-darwin64-538972.tar.bz2
-
- name
- darwin64
-
- linux64
-
- archive
-
- hash
- c1b43e99c5ddccc18b0e9cb288bf75e1
- url
- http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/4721/14828/llphysicsextensions_source-1.0.504710-linux64-504710.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- f3c066c1aebed8a6519a3e5ce64b9a3c
- url
- http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/54982/511796/llphysicsextensions_source-1.0.538972-windows-538972.tar.bz2
-
- name
- windows
-
-
- version
- 1.0.538972
-
- llphysicsextensions_stub
-
- copyright
- Copyright (c) 2010, Linden Research, Inc.
- license
- internal
- license_file
- LICENSES/llphysicsextensions.txt
- name
- llphysicsextensions_stub
- platforms
-
- darwin64
-
- archive
-
- hash
- f290b000b31f9e36f2489946cbc99f5e
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/59995/563653/llphysicsextensions_stub-1.0.542456-darwin64-542456.tar.bz2
-
- name
- darwin64
-
- linux64
-
- archive
-
- hash
- 711f4ec769e4b5f59ba25ee43c11bcbc
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/4724/14846/llphysicsextensions_stub-1.0.504712-linux64-504712.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- 2e5f1f7046a49d8b0bc295aa878116bc
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/60043/564063/llphysicsextensions_stub-1.0.542456-windows-542456.tar.bz2
-
- name
- windows
-
-
- version
- 1.0.542456
-
- llphysicsextensions_tpv
-
- copyright
- Copyright (c) 2010, Linden Research, Inc.
- license
- internal
- license_file
- LICENSES/HavokSublicense.pdf
- name
- llphysicsextensions_tpv
- platforms
-
- darwin64
-
- archive
-
- hash
- 2aa4ec0d72bbe4b755730f1bf92b39e7
- url
- http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/30340/257304/llphysicsextensions_tpv-1.0.542327-darwin64-542327.tar.bz2
-
- name
- darwin64
-
- linux64
-
- archive
-
- hash
- 711f4ec769e4b5f59ba25ee43c11bcbc
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/4724/14846/llphysicsextensions_stub-1.0.504712-linux64-504712.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- ad9aba5e2c43a37b6530a0d2de64df1c
- url
- http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/30341/257307/llphysicsextensions_tpv-1.0.542327-windows-542327.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- 46689ff1442a8eccac3a7f3258308e1e
- url
- http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/30341/257307/llphysicsextensions_tpv-1.0.542327-windows64-542327.tar.bz2
-
- name
- windows
-
-
- version
- 1.0.542327
-
- mesa
-
- license
- mesa
- license_file
- LICENSES/mesa.txt
- name
- mesa
- platforms
-
- linux
-
- archive
-
- hash
- 22c50a5d362cad311b4f413cfcffbba2
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/mesa_3p-update-mesa/rev/297294/arch/Linux/installer/mesa-7.11.1.297294-linux-297294.tar.bz2
-
- name
- linux
-
-
- version
- 7.11.1.297294
-
- nghttp2
-
- copyright
- Copyright (c) 2012, 2014, 2015, 2016 Tatsuhiro Tsujikawa
-Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
- description
- Library providing HTTP 2 support for libcurl
- license
- MIT
- license_file
- LICENSES/nghttp2.txt
- name
- nghttp2
- platforms
-
- darwin64
-
- archive
-
- hash
- e4f784d8a035c51921a1562ca7a1bab6
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76357/727350/nghttp2-1.40.0.555524-darwin64-555524.tar.bz2
-
- name
- darwin64
-
- linux
-
- archive
-
- hash
- 079c1a1bdb3ce1cda8ce3d7f75eeced3
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/9258/41585/nghttp2-1.25.0.509246-linux-509246.tar.bz2
-
- name
- linux
-
- linux64
-
- archive
-
- hash
- c3c5ff7d2f7ac1143ef8d888192d4a53
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/9257/41579/nghttp2-1.25.0.509246-linux64-509246.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- af05aa2994c9845308fecd094b7b2d25
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76359/727360/nghttp2-1.40.0.555524-windows-555524.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- 5a55cede40eef16b9d1e47c418a2b77a
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76358/727359/nghttp2-1.40.0.555524-windows64-555524.tar.bz2
-
- name
- windows64
-
-
- source_type
- hg
- version
- 1.40.0.555524
-
- nvapi
-
- copyright
- Copyright Β© 2012 NVIDIA Corporation. All rights reserved.
- description
- NVAPI provides an interface to NVIDIA devices.
- license
- NVIDIA Corporation Software License Agreement β NVAPI SDK
- license_file
- LICENSES/NVAPI_SDK_License_Agreement.pdf
- name
- nvapi
- platforms
-
- windows
-
- archive
-
- hash
- 4305515ad326c911a390388366a9107b
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54947/511704/nvapi-352.539058-windows-539058.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- 25c8ac919f24b8952653d38ec43640e5
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54945/511697/nvapi-352.539058-windows64-539058.tar.bz2
-
- name
- windows64
-
-
- version
- 352.539058
-
- ogg_vorbis
-
- copyright
- Copyright (c) 2002, Xiph.org Foundation
- description
- Audio encoding library
- license
- ogg-vorbis
- license_file
- LICENSES/ogg-vorbis.txt
- name
- ogg_vorbis
- platforms
-
- darwin
-
- archive
-
- hash
- 07fca1531a27915f642a5c1d95008d54
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/oggvorbis_3p-update-oggvorbis/rev/296878/arch/Darwin/installer/ogg_vorbis-1.2.2-1.3.2.296878-darwin-296878.tar.bz2
-
- name
- darwin
-
- darwin64
-
- archive
-
- hash
- a066f1d12caee1d87fc72f48169f9677
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54841/510071/ogg_vorbis-1.3.3-1.3.6.538971-darwin64-538971.tar.bz2
-
- name
- darwin64
-
- linux
-
- archive
-
- hash
- 5c9d94dce4551b19790057766ff939ea
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-oggvorbis/rev/314224/arch/Linux/installer/ogg_vorbis-1.2.2-1.3.2.314224-linux-314224.tar.bz2
-
- name
- linux
-
- linux64
-
- archive
-
- hash
- 45ebd074053dc9cae8c5c74b52085d4b
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/465/990/ogg_vorbis-1.2.2-1.3.2.500397-linux64-500397.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- d4b8ed3fd679a2b484d2d1a66c063908
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54981/511789/ogg_vorbis-1.3.3-1.3.6.538971-windows-538971.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- ec4a657fe639bb458ee5132062146a7a
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54980/511782/ogg_vorbis-1.3.3-1.3.6.538971-windows64-538971.tar.bz2
-
- name
- windows64
-
-
- version
- 1.3.3-1.3.6.538971
-
- open-libndofdev
-
- copyright
- Copyright (c) 2008, Jan Ciger (jan.ciger (at) gmail.com)
- description
- Open Source replacement for 3DConnection SDK
- license
- BSD
- license_file
- LICENSES/libndofdev.txt
- name
- open-libndofdev
- platforms
-
- linux
-
- archive
-
- hash
- b1245d467d5914a266efa16afeb55406
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/libndofdev_3p-update-libndofdev/rev/297553/arch/Linux/installer/open_libndofdev-0.3-linux-297553.tar.bz2
-
- name
- linux
-
-
- version
- 0.3
-
- openal
-
- copyright
- Creative Labs
- description
- OpenAL is a cross-platform 3D audio API appropriate for use with gaming applications and many other types of audio applications.
- license
- lgpl
- license_file
- LICENSES/openal.txt
- name
- openal
- platforms
-
- linux
-
- archive
-
- hash
- 24b91eda3831a51c7774644016c4cb09
- hash_algorithm
- md5
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-openal/rev/314223/arch/Linux/installer/openal-1.12.854-1.1.0.314223-linux-314223.tar.bz2
-
- name
- linux
-
- linux64
-
- archive
-
- hash
- 7530fab3979312da75a903d87b73e3a9
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-openal/rev/314223/arch/Linux/installer/openal-1.12.854-1.1.0.314223-linux64-314223.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- d9c86f79a6bb56a670e2801c33fd2dd1
- hash_algorithm
- md5
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-openal/rev/314223/arch/CYGWIN/installer/openal-1.12.854-1.1.0.314223-windows-314223.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- e0fdd9394a8cd8c6360b922f6f237e57
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-openal/rev/314223/arch/CYGWIN/installer/openal-1.12.854-1.1.0.314223-windows64-314223.tar.bz2
-
- name
- windows64
-
-
- version
- 1.12.854-1.1.0.314223
-
- openjpeg
-
- copyright
- Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium; Copyright (c) 2002-2007, Professor Benoit Macq; Copyright (c) 2001-2003, David Janssens; Copyright (c) 2002-2003, Yannick Verschueren; Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe; Copyright (c) 2005, Herve Drolon, FreeImage Team; Copyright (c) 2006-2007, Parvatha Elangovan; Copyright (c) 2008, Jerome Fimes, Communications & Systemes <jerome.fimes@c-s.fr>; Copyright (c) 2010-2011, Kaori Hagihara; Copyright (c) 2011-2012, Centre National d'Etudes Spatiales (CNES), France; Copyright (c) 2012, CS Systemes d'Information, France;
- description
- The OpenJPEG library is an open-source JPEG 2000 codec written in C language.
- license
- BSD
- license_file
- LICENSES/openjpeg.txt
- name
- openjpeg
- platforms
-
- darwin
-
- archive
-
- hash
- 2adb5b8bd2493d576c5d02b992d8f819
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/openjpeg_3p-update-openjpeg/rev/297018/arch/Darwin/installer/openjpeg-1.4.297018-darwin-297018.tar.bz2
-
- name
- darwin
-
- darwin64
-
- archive
-
- hash
- 5abf2d9c0b250821c59cc60cd94fd8af
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54840/510064/openjpeg-1.5.1.538970-darwin64-538970.tar.bz2
-
- name
- darwin64
-
- linux
-
- archive
-
- hash
- e82317482647559d46a818ba48e9423a
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-openjpeg/rev/314205/arch/Linux/installer/openjpeg-2.0.0.314205-linux-314205.tar.bz2
-
- name
- linux
-
- linux64
-
- archive
-
- hash
- ac66f3197010b1549a5e4467aebbc27d
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1113/2571/openjpeg-1.5.1.501102-linux64-501102.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- 222a406ecb4071a9cc9635353afa337e
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54977/511775/openjpeg-1.5.1.538970-windows-538970.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- 5b5c80807fa8161f3480be3d89fe9516
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54974/511767/openjpeg-1.5.1.538970-windows64-538970.tar.bz2
-
- name
- windows64
-
-
- version
- 1.5.1.538970
-
- openssl
-
- copyright
- Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved; Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- description
- Secure Sockets Layer (SSL v2/v3) and Transport Layer Security (TLS v1) Library
- license
- openssl
- license_file
- LICENSES/openssl.txt
- name
- openssl
- platforms
-
- darwin
-
- archive
-
- hash
- 0a77d56769e6075957f614be6575423e
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/openssl_3p-update-openssl/rev/297168/arch/Darwin/installer/openssl-1.0.1h.297168-darwin-297168.tar.bz2
-
- name
- darwin
-
- darwin64
-
- archive
-
- hash
- 5503e4928bcdb0a29685b3242c4a409b
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/82619/774464/openssl-1.1.1l.560177-darwin64-560177.tar.bz2
-
- name
- darwin64
-
- linux
-
- archive
-
- hash
- f46a601d60b7dbcfde32afc0cb64453e
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-openssl/rev/314227/arch/Linux/installer/openssl-1.0.1h.314227-linux-314227.tar.bz2
-
- name
- linux
-
- linux64
-
- archive
-
- hash
- d50ccfbf0c1d249392919e2c46ad8d5c
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/8339/33495/openssl-1.0.2l.508328-linux64-508328.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- d2153f20dc2d35c609b876a9f019a748
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/82623/774521/openssl-1.1.1l.560177-windows-560177.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- f40b8622ba38084b0962e273988d748f
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/82624/774520/openssl-1.1.1l.560177-windows64-560177.tar.bz2
-
- name
- windows64
-
-
- version
- 1.1.1l.560177
-
- pcre
-
- copyright
- Copyright (c) 1997-2014 University of Cambridge; Copyright(c) 2009-2014 Zoltan Herczeg; Copyright (c) 2007-2012, Google Inc.
- description
- PCRE Perl-compatible regular expression library
- license
- bsd
- license_file
- LICENSES/pcre-license.txt
- name
- pcre
- platforms
-
- darwin
-
- archive
-
- hash
- 6d2b38897f1adf354b299345d5fc759b
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/pcre_3p-update-pcre/rev/297155/arch/Darwin/installer/pcre-8.35.-darwin-297155.tar.bz2
-
- name
- darwin
-
- darwin64
-
- archive
-
- hash
- d8c0f97fe5abef43e72b6f84aba698b2
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/54856/510176/pcre-8.35.538986-darwin64-538986.tar.bz2
-
- name
- darwin64
-
- linux
-
- archive
-
- hash
- 24a119b18e63017ad932ad54df8161bc
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-pcre/rev/314136/arch/Linux/installer/pcre-8.35.314136-linux-314136.tar.bz2
-
- name
- linux
-
- linux64
-
- archive
-
- hash
- 0f058ca2176e7d02d51e54c66a96f336
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/908/2010/pcre-8.35.500898-linux64-500898.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- 3660db45793df3050b63920bfb7d8479
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/55041/512002/pcre-8.35.538986-windows-538986.tar.bz2
-
- name
- linux
-
- windows64
-
- archive
-
- hash
- cdee8e8b48a66266550bf279c40abc22
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/55038/511992/pcre-8.35.538986-windows64-538986.tar.bz2
-
- name
- windows64
-
-
- version
- 8.35.538986
-
- slvoice
-
- copyright
- 2010 Vivox, including audio coding using Polycom¨ Siren14TM (ITU-T Rec. G.722.1 Annex C)
- description
- Vivox SDK components
- license
- Mixed
- license_file
- LICENSES/vivox_licenses.txt
- name
- slvoice
- platforms
-
- darwin
-
- archive
-
- hash
- 511a9c3fd4b6c76a8a737d06bba1c291
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/oz-426-slvoice/rev/330003/arch/Darwin/installer/slvoice-4.9.0002.27586.330003-darwin-330003.tar.bz2
-
- name
- darwin
-
- darwin64
-
- archive
-
- hash
- 6ce3cbaed968a69fb7a2cca80220874d
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/80380/758537/slvoice-4.10.0000.32327.5fc3fe7c.558436-darwin64-558436.tar.bz2
-
- name
- darwin64
-
- linux
-
- archive
-
- hash
- 785c86999b56e1838cefb430f674cba7
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/oz-426-slvoice/rev/330003/arch/Linux/installer/slvoice-3.2.0002.10426.330003-linux-330003.tar.bz2
-
- name
- linux
-
- linux64
-
- archive
-
- hash
- 92b0ae08832bd0e99c34ef8f3e6346ad
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/613/1289/slvoice-3.2.0002.10426.500605-linux64-500605.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- 2eb38c5eff4d0f18fbb89d0c30c4f0a4
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/80382/758550/slvoice-4.10.0000.32327.5fc3fe7c.558436-windows-558436.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- 9ee8f3cbc5369c598a998c61961ed16d
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/80381/758551/slvoice-4.10.0000.32327.5fc3fe7c.558436-windows64-558436.tar.bz2
-
- name
- windows64
-
-
- version
- 4.10.0000.32327.5fc3fe7c.558436
-
- tracy
-
- canonical_repo
- https://bitbucket.org/lindenlab/3p-tracy
- copyright
- Copyright (c) 2017-2021, Bartosz Taudul (wolf@nereid.pl)
- description
- Tracy Profiler Library
- license
- bsd
- license_file
- LICENSES/tracy_license.txt
- name
- tracy
- platforms
-
- darwin64
-
- archive
-
- hash
- da7317e4a81609f624f84780f28b07de
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/86972/801630/tracy-v0.7.8.563351-darwin64-563351.tar.bz2
-
- name
- darwin64
-
- windows
-
- archive
-
- hash
- 47c696cd2966c5cc3c8ba6115dd1f886
- hash_algorithm
- md5
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/86973/801641/tracy-v0.7.8.563351-windows-563351.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- b649ee6591e67d2341e886b3fc3484a7
- hash_algorithm
- md5
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/86974/801642/tracy-v0.7.8.563351-windows64-563351.tar.bz2
-
- name
- windows64
-
-
- source
- https://bitbucket.org/lindenlab/3p-tracy
- source_type
- git
- version
- v0.7.8.563351
-
- tut
-
- copyright
- Copyright 2002-2006 Vladimir Dyuzhev, Copyright 2007 Denis Kononenko, Copyright 2008-2009 MichaΕ Rzechonek
- description
- TUT is a small and portable unit test framework for C++.
- license
- bsd
- license_file
- LICENSES/tut.txt
- name
- tut
- platforms
-
- common
-
- archive
-
- hash
- 64e1c979aea2f74fe9c2d9d04573336d
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/55001/511871/tut-2008.11.30-common-539059.tar.bz2
-
- name
- common
-
-
- version
- 2008.11.30
-
- uriparser
-
- copyright
- Copyright (C) 2007, Weijia Song <songweijia@gmail.com>, Sebastian Pipping <webmaster@hartwork.org>
- description
- uriparser is a strictly RFC 3986 compliant URI parsing and handling library written in C. uriparser is cross-platform, fast, supports Unicode and is licensed under the New BSD license.
- license
- New BSD license
- license_file
- LICENSES/uriparser.txt
- name
- uriparser
- platforms
-
- darwin
-
- archive
-
- hash
- 22608adaf54e8ddc9182a719ba6e2b32
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/uriparser_3p-update-uriparser/rev/299435/arch/Darwin/installer/uriparser-0.8.0.1-darwin-299435.tar.bz2
-
- name
- darwin
-
- darwin64
-
- archive
-
- hash
- c42575ac8997de979eadb082c33a578e
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/81322/765512/uriparser-0.9.4-darwin64-559132.tar.bz2
-
- name
- darwin64
-
- linux
-
- archive
-
- hash
- dddfc8dea540801f93ba0382cb1e3685
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/uriparser_3p-update-uriparser/rev/299435/arch/Linux/installer/uriparser-0.8.0.1-linux-299435.tar.bz2
-
- name
- linux
-
- linux64
-
- archive
-
- hash
- 087375378f104cdac0cb0fe0ca43dd4d
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/346/880/uriparser-0.8.0.1-linux64-500342.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- 901b1063556fc6b2575e745eef2bf744
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/81323/765528/uriparser-0.9.4-windows-559132.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- 962c01d553f286c430102998129fb0d6
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/81324/765527/uriparser-0.9.4-windows64-559132.tar.bz2
-
- name
- windows64
-
-
- version
- 0.9.4
-
- viewer-manager
-
- copyright
- Copyright (c) 2000-2012, Linden Research, Inc.
- description
- Linden Lab Viewer Management Process suite.
- license
- viewerlgpl
- license_file
- LICENSE
- name
- viewer-manager
- platforms
-
- darwin64
-
- archive
-
- hash
- 6989053898b8e81e904e75553e378820
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/77523/735051/viewer_manager-2.0.556340-darwin64-556340.tar.bz2
-
- name
- darwin64
-
- linux
-
- archive
-
- hash
- 8c7f32f85850248809ae811ba8e47d81
- url
- http://s3-proxy.lindenlab.com/private-builds-secondlife-com/ct2/3428/8686/viewer_manager-1.0-linux-503417.tar.bz2
-
- name
- linux
-
- windows
-
- archive
-
- hash
- 3446c1e54bb32542677caad0ec0d42ac
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/77525/735058/viewer_manager-2.0.556340-windows-556340.tar.bz2
-
- name
- windows
-
-
- source
- https://bitbucket.org/lindenlab/vmp-standalone
- source_type
- hg
- version
- 2.0.556340
-
- vlc-bin
-
- copyright
- Copyright (C) 1998-2016 VLC authors and VideoLAN
- license
- GPL2
- license_file
- LICENSES/vlc.txt
- name
- vlc-bin
- platforms
-
- darwin64
-
- archive
-
- hash
- b639d0035f4a8c9b4973be428a1b7e61
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/69569/671323/vlc_bin-3.0.9.549888-darwin64-549888.tar.bz2
-
- name
- darwin64
-
- linux
-
- archive
-
- hash
- 2f410640df3f9812d1abff02a414cfa8
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-vlc-bin/rev/315283/arch/Linux/vlc_bin-2.2.3-linux-201606011750-r10.tar.bz2
-
- name
- linux
-
- windows
-
- archive
-
- hash
- 4f50b0c47daa081dd4fcb83763d5b0b2
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/69567/671314/vlc_bin-3.0.9.549888-windows-549888.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- c2f8c01fb6c261b72beb07f0c4cd423f
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/69568/671315/vlc_bin-3.0.9.549888-windows64-549888.tar.bz2
-
- name
- windows64
-
-
- version
- 3.0.9.549888
-
- xmlrpc-epi
-
- copyright
- Copyright: (C) 2000 Epinions, Inc.
- description
- XMLRPC Library
- license
- xmlrpc-epi
- license_file
- LICENSES/xmlrpc-epi.txt
- name
- xmlrpc-epi
- platforms
-
- darwin
-
- archive
-
- hash
- ffd3aab8e0c0ff6dadbce49ca2809078
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/xmlrpc-emi_3p-update-xmlrpc-epi/rev/297075/arch/Darwin/installer/xmlrpc_epi-0.54.1.297075-darwin-297075.tar.bz2
-
- name
- darwin
-
- darwin64
-
- archive
-
- hash
- 922a0dea32266897ed1911200438e1e1
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76372/727426/xmlrpc_epi-0.54.1.555529-darwin64-555529.tar.bz2
-
- name
- darwin64
-
- linux
-
- archive
-
- hash
- b63f828e798287d475991134cdcfbca3
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-xmlrpc-epi/rev/314240/arch/Linux/installer/xmlrpc_epi-0.54.1.314240-linux-314240.tar.bz2
-
- name
- linux
-
- linux64
-
- archive
-
- hash
- 35df17c3eb673030dea4bde9191aa506
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/727/1489/xmlrpc_epi-0.54.1.500719-linux64-500719.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- 34b847e6b280048465fe7c6ce67fe05c
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76374/727436/xmlrpc_epi-0.54.1.555529-windows-555529.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- 8fbe7c4ea22bb7f23a93c73884ebb34c
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/76373/727435/xmlrpc_epi-0.54.1.555529-windows64-555529.tar.bz2
-
- name
- windows64
-
-
- version
- 0.54.1.555529
-
- zlib
-
- copyright
- Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
- description
- Zlib Data Compression Library
- license
- zlib
- license_file
- LICENSES/zlib.txt
- name
- zlib
- platforms
-
- darwin
-
- archive
-
- hash
- 1a79eeac199c2d94e4ae4e5d0194e25f
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/zlib_3p-update-zlib/rev/296881/arch/Darwin/installer/zlib-1.2.8.296881-darwin-296881.tar.bz2
-
- name
- darwin
-
- darwin64
-
- archive
-
- hash
- 9181bc8229f1a8e480d2a40a2744ec28
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78578/743913/zlib-1.2.11.557041-darwin64-557041.tar.bz2
-
- name
- darwin64
-
- linux
-
- archive
-
- hash
- 98a8c775c581ca80bb559e8b4e8eaae7
- hash_algorithm
- md5
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/p64_3p-zlib/rev/314131/arch/Linux/installer/zlib-1.2.8.314131-linux-314131.tar.bz2
-
- name
- linux
-
- linux64
-
- archive
-
- hash
- dab6be8b0596c1e3354f2b6d41335131
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/866/1898/zlib-1.2.8.500857-linux64-500857.tar.bz2
-
- name
- linux64
-
- windows
-
- archive
-
- hash
- 8308cbd2ea0fe290541698b0f63482e2
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78579/743926/zlib-1.2.11.557041-windows-557041.tar.bz2
-
- name
- windows
-
- windows64
-
- archive
-
- hash
- 36bdc34f67d3ad3c57125dc1b16a3129
- url
- https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/78577/743920/zlib-1.2.11.557041-windows64-557041.tar.bz2
-
- name
- windows64
-
-
- version
- 1.2.11.557041
-
-
- package_description
-
- canonical_repo
- https://bitbucket.org/lindenlab/viewer
- copyright
- Copyright (c) 2020, Linden Research, Inc.
- description
- Second Life Viewer
- license
- LGPL
- license_file
- docs/LICENSE-source.txt
- name
- Second Life Viewer
- platforms
-
- common
-
- configurations
-
- RelWithDebInfo
-
- build
-
-
- configure
-
- command
- cmake
- options
-
- -DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo
- -DADDRESS_SIZE:STRING=$AUTOBUILD_ADDRSIZE
- -DROOT_PROJECT_NAME:STRING=SecondLife
- -DINSTALL_PROPRIETARY=TRUE
-
-
- name
- RelWithDebInfo
-
- RelWithDebInfoOS
-
- configure
-
- arguments
-
- ../indra
-
- command
- cmake
- options
-
- -DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo
- -DADDRESS_SIZE:STRING=$AUTOBUILD_ADDRSIZE
- -DROOT_PROJECT_NAME:STRING=SecondLife
- -DINSTALL_PROPRIETARY=FALSE
-
-
- name
- RelWithDebInfoOS
-
- Release
-
- build
-
-
- configure
-
- command
- cmake
- options
-
- -DCMAKE_BUILD_TYPE:STRING=Release
- -DADDRESS_SIZE:STRING=$AUTOBUILD_ADDRSIZE
- -DROOT_PROJECT_NAME:STRING=SecondLife
- -DINSTALL_PROPRIETARY=TRUE
-
-
- name
- Release
-
- ReleaseOS
-
- configure
-
- arguments
-
- ../indra
-
- command
- cmake
- options
-
- -DCMAKE_BUILD_TYPE:STRING=Release
- -DADDRESS_SIZE:STRING=$AUTOBUILD_ADDRSIZE
- -DROOT_PROJECT_NAME:STRING=SecondLife
- -DINSTALL_PROPRIETARY=FALSE
-
-
- name
- ReleaseOS
-
-
- name
- common
-
- darwin64
-
- build_directory
- build-darwin-x86_64
- configurations
-
- RelWithDebInfo
-
- build
-
- command
- xcodebuild
- options
-
- -configuration
- RelWithDebInfo
- -project
- SecondLife.xcodeproj
-
-
- configure
-
- arguments
-
- ../indra
-
- options
-
- -G
- Xcode
-
-
- default
- True
- name
- RelWithDebInfo
-
- RelWithDebInfoOS
-
- build
-
- command
- xcodebuild
- options
-
- -configuration
- RelWithDebInfo
- -project
- SecondLife.xcodeproj
-
-
- configure
-
- options
-
- -G
- Xcode
-
-
- name
- RelWithDebInfoOS
-
- Release
-
- build
-
- command
- xcodebuild
- options
-
- -configuration
- Release
- -project
- SecondLife.xcodeproj
-
-
- configure
-
- arguments
-
- ../indra
-
- options
-
- -G
- Xcode
-
-
- name
- Release
-
- ReleaseOS
-
- build
-
- command
- xcodebuild
- options
-
- -configuration
- Release
- -project
- SecondLife.xcodeproj
-
-
- configure
-
- options
-
- -G
- Xcode
-
-
- name
- ReleaseOS
-
-
- name
- darwin64
-
- linux
-
- build_directory
- build-linux-i686
- configurations
-
- RelWithDebInfo
-
- build
-
- command
- make
- options
-
- -j
- 12
-
-
- configure
-
- arguments
-
- ../indra
-
- options
-
- -G
- Unix Makefiles
-
-
- default
- True
- name
- RelWithDebInfo
-
- RelWithDebInfoOS
-
- build
-
- command
- make
- options
-
- -j
- 7
-
-
- configure
-
- options
-
- -G
- Unix Makefiles
-
-
- name
- RelWithDebInfoOS
-
- Release
-
- build
-
- command
- make
- options
-
- -j
- 12
-
-
- configure
-
- arguments
-
- ../indra
-
- options
-
- -G
- Unix Makefiles
-
-
- name
- Release
-
- ReleaseOS
-
- build
-
- command
- make
- options
-
- -j
- 7
-
-
- configure
-
- options
-
- -G
- Unix Makefiles
-
-
- name
- ReleaseOS
-
- default
-
- build
-
-
- name
- default
-
-
- name
- linux
-
- windows
-
- build_directory
- build-vc${AUTOBUILD_VSVER|150}-$AUTOBUILD_ADDRSIZE
- configurations
-
- RelWithDebInfo
-
- build
-
- arguments
-
- SecondLife.sln
-
- command
- devenv
- options
-
- /build
- RelWithDebInfo|${AUTOBUILD_WIN_VSPLATFORM|NOTWIN}
-
-
- configure
-
- arguments
-
- ..\indra
-
- options
-
- -G
- ${AUTOBUILD_WIN_CMAKE_GEN|NOTWIN}
-
-
- default
- True
- name
- RelWithDebInfo
-
- RelWithDebInfoOS
-
- build
-
- arguments
-
- SecondLife.sln
-
- command
- msbuild.exe
- options
-
- /p:Configuration=RelWithDebInfo
- /p:Platform=${AUTOBUILD_WIN_VSPLATFORM|NOTWIN}
- /t:Build
- /p:useenv=true
- /verbosity:minimal
- /toolsversion:4.0
- /p:VCBuildAdditionalOptions= /incremental
-
-
- configure
-
- arguments
-
- ..\indra
-
- options
-
- -G
- ${AUTOBUILD_WIN_CMAKE_GEN|NOTWIN}
- -DINSTALL_PROPRIETARY=FALSE
- -DUSE_KDU=FALSE
- -DOPENAL:BOOL=ON
-
-
- name
- RelWithDebInfoOS
-
- Release
-
- build
-
- arguments
-
- SecondLife.sln
-
- command
- devenv
- options
-
- /build
- Release|${AUTOBUILD_WIN_VSPLATFORM|NOTWIN}
-
-
- configure
-
- arguments
-
- ..\indra
-
- options
-
- -G
- ${AUTOBUILD_WIN_CMAKE_GEN|NOTWIN}
-
-
- name
- Release
-
- ReleaseOS
-
- build
-
- arguments
-
- SecondLife.sln
-
- command
- msbuild.exe
- options
-
- /p:Configuration=Release
- /p:Platform=${AUTOBUILD_WIN_VSPLATFORM|NOTWIN}
- /t:Build
- /p:useenv=true
- /verbosity:minimal
- /toolsversion:4.0
- /p:VCBuildAdditionalOptions= /incremental
-
-
- configure
-
- arguments
-
- ..\indra
-
- options
-
- -G
- ${AUTOBUILD_WIN_CMAKE_GEN|NOTWIN}
- -DUNATTENDED:BOOL=ON
- -DINSTALL_PROPRIETARY=FALSE
- -DUSE_KDU=FALSE
- -DOPENAL:BOOL=ON
-
-
- name
- ReleaseOS
-
-
- name
- windows
-
-
- version_file
- newview/viewer_version.txt
-
- type
- autobuild
- version
- 1.3
-
-
diff --git a/tests/fuzz.py b/tests/fuzz.py
deleted file mode 100644
index fb48ff0..0000000
--- a/tests/fuzz.py
+++ /dev/null
@@ -1,465 +0,0 @@
-from __future__ import division
-
-import random
-import string
-import struct
-import time
-import uuid
-from datetime import date, datetime, timedelta
-
-# Ridiculous optimization -- compute once ahead of time so choice() doesn't
-# call len(string.printable) a bajillion times. Amazing it makes a difference.
-printable_len = len(string.printable)
-
-
-import llsd
-from llsd.base import is_string
-
-
-class LLSDFuzzer(object):
- """Generator of fuzzed LLSD objects.
-
- The :class:`LLSDFuzzer` constructor accepts a *seed* argument, which becomes the
- seed of the PRNG driving the fuzzer. If *seed* is None, the current time is
- used. The seed is also stored in the seed attribute on the object, which
- is useful for producing deterministic trials.
- """
- def __init__(self, seed=None):
- self.r = random.Random()
- if seed is None:
- seed = time.time()
- self.seed = seed
- self.r.seed(seed)
-
- def random_boolean(self):
- """Returns a random boolean."""
- return bool(self.r.getrandbits(1))
-
- def random_integer(self):
- """Returns a random integral value."""
- return self.r.getrandbits(32) - 2**31
-
- def random_real(self):
- """Returns a random floating-point value."""
- return self.r.uniform(-1000000.0, 1000000.0)
-
- def random_uuid(self):
- """Returns a random UUID object."""
- # use bytes from our local Random, instead of the various uuid
- # constructors, so as to be completely deterministic
- return uuid.UUID(int= self.r.getrandbits(128))
-
- def _string_length(self):
- """Returns a 'reasonable' random length for a string. The current
- distribution is such that it usually returns a number less than 25, but
- occasionally can return numbers as high as a few thousand."""
- return int(self.r.lognormvariate(2.7, 1.3))
-
- def random_printable(self, length = None):
- """Returns a string of random printable characters with length *length*.
- Uses a random length if none is specified."""
- if length is None:
- length = self._string_length()
- return ''.join([string.printable[int(self.r.random() * printable_len)]
- for x in range(length)])
-
- def random_unicode(self, length = None):
- """Returns a string of random unicode characters with length *length*.
- Uses a random length if none is specified."""
- # length of the unicode string will be only vaguely
- # close to the specified length because we're not bothering
- # to generate valid utf-16 and therefore many of our
- # bytes may be discarded as invalid
- if length is None:
- length = self._string_length()
- bytes = self.random_bytes(length * 2)
- # utf-16 instead of utf-8 or 32 because it's way faster
- return bytes.decode('utf-16', 'ignore')
-
- def random_bytes(self, length = None):
- """Returns a string of random bytes with length *length*.
- Uses a random length if none is specified."""
- if length is None:
- length = self._string_length()
-
- if length % 8 == 0:
- num_chunks = length // 8
- else:
- num_chunks = length // 8 + 1
-
- # this appears to be the fastest way to generate random byte strings
- packstr = 'Q'*num_chunks
- randchunks = [self.r.getrandbits(64) for i in range(num_chunks)]
- return struct.pack(packstr, *randchunks)[:length]
-
- def random_binary(self, length=None):
- """Returns a random llsd.binary object containing *length* random
- bytes. Uses a random length if none is specified."""
- return llsd.binary(self.random_bytes(length))
-
- def random_date(self):
- """Returns a random date within the range of allowed LLSD dates (1970
- to 2038)"""
- return datetime.utcfromtimestamp(0) + \
- timedelta(seconds=self.r.getrandbits(31))
-
- def random_uri(self, length=None):
- """Returns a random llsd.uri object containing *length* random
- printable characters (so, not necessarily a legal uri). Uses a random
- length if none is specified."""
- return llsd.uri(self.random_printable(length))
-
- def _container_size(self):
- "Returns a random 'reasonable' container size."
- return int(round(self.r.expovariate(0.3)+1))
-
- def random_map(self):
- """Returns a Python dictionary which has string keys and
- randomly-chosen values. It is single-level; none of the
- values are themselves maps or arrays."""
- retval = {}
- for x in range(self._container_size()):
- if self.random_boolean():
- key = self.random_unicode()
- else:
- key = self.random_printable()
- value = self.random_atom(include_containers=False)
- retval[key] = value
- return retval
-
- def random_array(self):
- """Returns a random Python array which is populated
- with random values. It is single-level; none of the
- values are themselves maps or arrays."""
- return [self.random_atom(include_containers=False)
- for x in range(self._container_size())]
-
- random_generators = [
- lambda self: None,
- random_boolean,
- random_integer,
- random_real,
- random_uuid,
- random_printable,
- random_unicode,
- random_binary,
- random_date,
- random_uri,
- random_map,
- random_array]
-
- def random_atom(self, include_containers=True):
- """Returns a random LLSD atomic value."""
- if include_containers:
- return self.r.choice(self.random_generators)(self)
- else:
- return self.r.choice(self.random_generators[:-2])(self)
-
- def permute_undef(self, val):
- """Permutes undef, the return value is always None."""
- return None
-
- def permute_boolean(self, val):
- """Permutes booleans, the return value is always a boolean."""
- return self.random_boolean()
-
- integer_options = [
- lambda s, v: -v,
- lambda s, v: 0,
- lambda s, v: v + s.r.randint(-(v**4), (v**4)),
- lambda s, v: 4294967296, # 2^32
- lambda s, v: -2147483649, # -2^31 - 1
- lambda s, v: 18446744073709551616, # 2^64
- lambda s, v: s.random_integer(),
- lambda s, v: v * ((s.r.getrandbits(16) - 2**15) or 1),
- lambda s, v: v // ((s.r.getrandbits(16) - 2**15) or 1),
- lambda s, v: v + s.random_integer(),
- lambda s, v: v - s.random_integer(),
- lambda s, v: v * ((s.r.getrandbits(8) - 2**7) or 1),
- lambda s, v: v // ((s.r.getrandbits(8) - 2**7) or 1)
- ]
-
- def permute_integer(self, val):
- """Generates variations on a given int or long,
- returned value is an int or a long."""
- return self.r.choice(self.integer_options)(self, val)
-
- real_options = [
- lambda s, v: -v,
- lambda s, v: 0.0,
- lambda s, v: v/float(2**64),
- lambda s, v: v*float(2**64),
- lambda s, v: 1E400,
- lambda s, v: -1E400,
- lambda s, v: float('nan'),
- lambda s, v: s.random_real(),
- lambda s, v: v * (s.r.random() - 0.5),
- lambda s, v: v / (s.r.random() - 0.5),
- lambda s, v: v + s.random_real(),
- lambda s, v: v - s.random_real(),
- lambda s, v: v * s.random_real(),
- lambda s, v: v / s.random_real()
- ]
-
- def permute_real(self, val):
- """Generates variations on a float, the returned
- value is a float."""
- return self.r.choice(self.real_options)(self, val)
-
- def permute_uuid(self, val):
- """ Generates variations on a uuid, the returned value is a uuid."""
- return uuid.UUID(int=self.r.getrandbits(128) ^ val.int)
-
- def rand_idx(self, val):
- """Return a random index into the value."""
- if len(val) == 0:
- return 0
- return self.r.randrange(0, len(val))
-
- stringlike_options = [
- lambda s,v,strgen: strgen() + v,
- lambda s,v,strgen: v + strgen(),
- lambda s,v,strgen: v[s.rand_idx(v):],
- lambda s,v,strgen: v[:s.rand_idx(v)],
- lambda s,v,strgen: v[:s.rand_idx(v)] + strgen() + v[s.rand_idx(v):]
- ]
-
- def _permute_stringlike(self, val, strgen):
- if len(val) == 0:
- return strgen()
- else:
- return self.r.choice(self.stringlike_options)(self, val, strgen)
-
- def permute_string(self, val):
- """Generates variations on a given string or unicode. All
- generated values are strings/unicodes."""
- assert is_string(val)
- def string_strgen(length = None):
- if self.random_boolean():
- return self.random_printable(length)
- else:
- return self.random_unicode(length)
- return self._permute_stringlike(val, string_strgen)
-
- def permute_binary(self, val):
- """Generates variations on a given binary value. All
- generated values are llsd.binary."""
- assert isinstance(val, llsd.binary)
- return llsd.binary(self._permute_stringlike(val, self.random_bytes))
-
- def _date_clamp(self, val):
- if val.year >= 2038:
- raise OverflowError()
- elif val.year < 1970:
- return date(1970, val.month, val.day)
- else:
- return val
-
- date_options = [
- lambda s, v: s._date_clamp(v + timedelta(
- seconds=s.r.getrandbits(21) - 2**20,
- microseconds=s.r.getrandbits(20))),
- lambda s, v: datetime.utcfromtimestamp(0),
- lambda s, v: date(v.year, v.month, v.day),
- lambda s, v: datetime.utcfromtimestamp(2**31-86400),
- ]
-
- def permute_date(self, val):
- """Generates variations on a given datetime. All generated
- values are datetimes within the valid llsd daterange."""
- assert isinstance(val, (datetime, date))
- # have to retry a few times because the random-delta option
- # sometimes gets out of range
- while True:
- try:
- return self.r.choice(self.date_options)(self, val)
- except (OverflowError, OSError):
- continue
-
- def permute_uri(self, val):
- """Generates variations on a given uri. All
- generated values are llsd.uri."""
- assert isinstance(val, llsd.uri)
- return llsd.uri(self._permute_stringlike(val, self.random_printable))
-
- def _permute_map_permute_value(self, val):
- if len(val) == 0:
- return {}
- # choose one of the keys from val
- k = self.r.choice(list(val))
- permuted = val.copy()
- permuted[k] = next(self.structure_fuzz(val[k]))
- return permuted
-
- def _permute_map_key_delete(self, val):
- if len(val) == 0:
- return {}
- # choose one of the keys from val
- k = self.r.choice(list(val))
- permuted = val.copy()
- permuted.pop(k, None)
- return permuted
-
- def _permute_map_new_key(self, val):
- permuted = val.copy()
- if len(val) > 0 and self.random_boolean():
- # choose one of the keys from val
- new_key = self.permute_string(self.r.choice(list(val)))
- else:
- new_key = self.random_unicode()
-
- permuted[new_key] = self.random_atom()
- return permuted
-
- def _permute_map_permute_key_names(self, val):
- if len(val) == 0:
- return {}
- # choose one of the keys from val
- k = self.r.choice(list(val))
- k = self.permute_string(k)
- permuted = val.copy()
- v = permuted.pop(k, None)
- permuted[k] = v
- return permuted
-
-
- map_sub_permuters = (_permute_map_permute_value,
- _permute_map_permute_value,
- _permute_map_key_delete,
- _permute_map_new_key,
- _permute_map_permute_key_names)
-
- def permute_map(self, val):
- """ Generates variations on an input dict via a variety of steps.
- The return value is a dict."""
- assert isinstance(val, dict)
- permuted = self.r.choice(self.map_sub_permuters)(self, val)
- for i in range(int(self.r.expovariate(0.5)) + 1):
- permuted = self.r.choice(self.map_sub_permuters)(self, permuted)
- return permuted
-
- def _permute_array_permute_value(self, val):
- idx = self.r.randrange(0, len(val))
- permuted = list(val)
- permuted[idx] = next(self.structure_fuzz(val[idx]))
- return permuted
-
- def _permute_array_subsets(self, val):
- return self.r.sample(val, self.r.randint(1, len(val)))
-
- def _permute_array_inserting(self, val):
- new_idx = self.r.randint(0, len(val))
- inserted = self.random_atom()
- permuted = list(val[:new_idx]) + [inserted] + list(val[new_idx:])
- return permuted
-
- def _permute_array_reorder(self, val):
- permuted = list(val)
- swaps = self.r.randrange(0, len(val))
- for s in range(swaps):
- i = self.r.randrange(0, len(val))
- j = self.r.randrange(0, len(val))
- permuted[i], permuted[j] = permuted[j], permuted[i]
- return permuted
-
- array_sub_permuters = (_permute_array_permute_value,
- _permute_array_permute_value,
- _permute_array_subsets,
- _permute_array_inserting,
- _permute_array_reorder)
-
- def permute_array(self, val):
- """ Generates variations on an input array via a variety of steps.
- The return value is a dict."""
- assert isinstance(val, (list, tuple))
- permuted = self.r.choice(self.array_sub_permuters)(self, val)
- for i in range(int(self.r.expovariate(0.5)) + 1):
- permuted = self.r.choice(self.array_sub_permuters)(self, permuted)
- if self.random_boolean():
- permuted = tuple(permuted)
- return permuted
-
- permuters = {
- type(None): permute_undef,
- bool: permute_boolean,
- int: permute_integer,
- llsd.LongType: permute_integer,
- float: permute_real,
- uuid.UUID: permute_uuid,
- str: permute_string,
- llsd.UnicodeType: permute_string,
- llsd.binary: permute_binary,
- datetime: permute_date,
- date: permute_date,
- llsd.uri: permute_uri,
- dict: permute_map,
- list: permute_array,
- tuple: permute_array}
-
- def structure_fuzz(self, starting_structure):
- """ Generates a series of Python structures
- based on the input structure."""
- permuter = self.permuters[type(starting_structure)]
- while True:
- if self.r.getrandbits(2) == 0:
- yield self.random_atom()
- else:
- yield permuter(self, starting_structure)
-
- def _random_numeric(self, length):
- return ''.join([self.r.choice(string.digits)
- for x in range(length)])
-
- def _dirty(self, val):
- idx1 = self.rand_idx(val)
- idx2 = idx1 + int(round(self.r.expovariate(0.1)))
- if self.random_boolean():
- # replace with same-length string
- subst_len = idx2 - idx1
- else:
- subst_len = int(round(self.r.expovariate(0.1)))
-
- if self.random_boolean():
- # use printable
- if self.random_boolean():
- replacement = self._random_numeric(subst_len).encode('latin-1')
- else:
- replacement = self.random_printable(subst_len).encode('latin-1')
- else:
- replacement = self.random_bytes(subst_len)
-
- return val[:idx1] + replacement + val[idx2:]
-
- def _serialized_fuzz(self, it, formatter):
- while True:
- struct = next(it)
- try:
- text = formatter(struct)
- except llsd.LLSDSerializationError:
- continue
- yield text
- dirtied = self._dirty(text)
- for i in range(int(round(self.r.expovariate(0.3)))):
- dirtied = self._dirty(dirtied)
- yield dirtied
-
- def binary_fuzz(self, starting_structure):
- """ Generates a series of strings which are meant to be tested against
- a service that parses binary LLSD."""
- return self._serialized_fuzz(
- self.structure_fuzz(starting_structure),
- llsd.format_binary)
-
- def xml_fuzz(self, starting_structure):
- """ Generates a series of strings which are meant to be tested against
- a service that parses XML LLSD."""
- return self._serialized_fuzz(
- self.structure_fuzz(starting_structure),
- llsd.format_xml)
-
- def notation_fuzz(self, starting_structure):
- """ Generates a series of strings which are meant to be tested against
- a service that parses the LLSD notation serialization."""
- return self._serialized_fuzz(
- self.structure_fuzz(starting_structure),
- llsd.format_notation)
\ No newline at end of file
diff --git a/tests/llsd_test.py b/tests/llsd_test.py
deleted file mode 100644
index 073a974..0000000
--- a/tests/llsd_test.py
+++ /dev/null
@@ -1,1979 +0,0 @@
-
-# -*- coding: utf-8 -*-
-from __future__ import print_function
-
-import base64
-from datetime import date, datetime
-import io
-from itertools import islice
-import pprint
-import re
-import struct
-import time
-import unittest
-import uuid
-from os import path
-
-import pytest
-
-import llsd
-from llsd.base import PY2, is_integer, is_string, is_unicode, MAX_FORMAT_DEPTH
-from llsd.serde_xml import remove_invalid_xml_bytes
-from tests.fuzz import LLSDFuzzer
-
-FIXTURES_DIR = path.join(path.dirname(__file__), 'fixtures')
-
-
-class Foo(object):
- """
- Simple Mock Class used for testing.
- """
- pass
-
-try:
- from math import isnan as _isnan
- def isnan(x):
- if isinstance(x, float):
- return _isnan(x)
- else:
- return False
-except ImportError:
- def isnan(x):
- return x != x
-
-
-class LLSDNotationUnitTest(unittest.TestCase):
- """
- This class aggregates all the tests for parse_notation(something),
- LLSD.as_notation(something) and format_notation (i.e. same as
- LLSD.as_notation(something). Note that test scenarios for the
- same input type are all put into single test method. And utility
- method assert_notation_roundtrip is used to test parse_notation
- and as_notation at the same time.
- """
- def setUp(self):
- """
- Set up the test class
- """
- self.llsd = llsd.LLSD()
-
- def strip(self, the_string):
- """
- Remove any whitespace characters from the input string.
-
- :Parameters:
- - 'the_string': string to remove the whitespaces.
- """
- return re.sub(br'\s', b'', the_string)
-
- def assertNotationRoundtrip(self, py_in, str_in, is_alternate_notation=False):
- """
- Utility method to check the result of parse_notation and
- LLSD.as_notation.
- """
- # use parse to check here
- py_out = self.llsd.parse(str_in)
- py_out2 = self.llsd.parse(io.BytesIO(str_in))
- self.assertEqual(py_out2, py_out)
- str_out = self.llsd.as_notation(py_in)
- py_roundtrip = self.llsd.parse(str_out)
- py_roundtrip2 = self.llsd.parse(io.BytesIO(str_out))
- self.assertEqual(py_roundtrip2, py_roundtrip)
- str_roundtrip = self.llsd.as_notation(py_out)
- # compare user-passed Python data with parsed user-passed string
- self.assertEqual(py_in, py_out)
- # compare user-passed Python data with parsed (serialized data)
- self.assertEqual(py_in, py_roundtrip)
-
-## # Comparing serialized data invites exasperating spurious test
-## # failures. Most interesting LLSD data is contained in dicts, and
-## # Python has never guaranteed the serialization order of dict keys.
-## # If str_in is an alternate notation, we can't compare it directly.
-## if not is_alternate_notation:
-## self.assertEqual(self.strip(str_out), self.strip(str_in))
-## self.assertEqual(self.strip(str_out), self.strip(str_roundtrip))
-
- # use parse_notation to check again
- py_out = llsd.parse_notation(str_in)
- str_out = self.llsd.as_notation(py_in)
- py_roundtrip = llsd.parse_notation(str_out)
- str_roundtrip = self.llsd.as_notation(py_out)
- self.assertEqual(py_in, py_out)
- self.assertEqual(py_in, py_roundtrip)
-
-## # Disabled for the same reason as above.
-## # If str_in is an alternate notation, we can't compare it directly.
-## if not is_alternate_notation:
-## self.assertEqual(self.strip(str_out), self.strip(str_in))
-## self.assertEqual(self.strip(str_out), self.strip(str_roundtrip))
-
- def testInteger(self):
- """
- Test the input type integer.
- Maps to test scenarios module:llsd:test#4-6
- """
- pos_int_notation = b"i123456"
- neg_int_notation = b"i-123457890"
- blank_int_notation = b"i0"
-
- python_pos_int = 123456
- python_neg_int = -123457890
-
- self.assertNotationRoundtrip(python_pos_int,
- pos_int_notation)
- self.assertNotationRoundtrip(python_neg_int,
- neg_int_notation)
- self.assertEqual(0, self.llsd.parse(blank_int_notation))
-
- def testUndefined(self):
- """
- Test the input type : undef
- Maps to test scenarios module:llsd:test#7
- """
- undef_notation = b"!"
- self.assertNotationRoundtrip(None, undef_notation)
-
- def testBoolean(self):
- """
- Test the input type : Boolean
- Maps to test scenarios module:llsd:test#8-17
- """
- sample_data = [(True, b"TRUE"),
- (True, b"true"),
- (True, b"T"),
- (True, b"t"),
- (True, b"1"),
- (False, b"FALSE"),
- (False, b"false"),
- (False, b"F"),
- (False, b"f"),
- (False, b"0")
- ]
- for py, notation in sample_data:
- is_alternate_notation = False
- if notation not in (b"true", b"false"):
- is_alternate_notation = True
- self.assertNotationRoundtrip(py, notation, is_alternate_notation)
-
- blank_notation = b""
- self.assertEqual(False, self.llsd.parse(blank_notation))
-
- def testReal(self):
- """
- Test the input type: real.
- Maps to test scenarios module:llsd:test#18-20
- """
- pos_real_notation = b"r2983287453.3000002"
- neg_real_notation = b"r-2983287453.3000002"
- blank_real_notation = b"r0"
-
- python_pos_real = 2983287453.3
- python_neg_real = -2983287453.3
-
- self.assertNotationRoundtrip(python_pos_real,
- pos_real_notation, True)
- self.assertNotationRoundtrip(python_neg_real,
- neg_real_notation, True)
- self.assertEqual(0, self.llsd.parse(blank_real_notation))
-
-
- def testUUID(self):
- """
- Test the input type : UUID.
- Maps to test scenarios module:llsd:test#21
- """
- uuid_tests = {
- uuid.UUID(hex='d7f4aeca-88f1-42a1-b385-b9db18abb255'):b"ud7f4aeca-88f1-42a1-b385-b9db18abb255",
- uuid.UUID(hex='00000000-0000-0000-0000-000000000000'):b"u00000000-0000-0000-0000-000000000000"}
-
- for py, notation in uuid_tests.items():
- self.assertNotationRoundtrip(py, notation)
-
- def testString(self):
- """
- Test the input type: String.
- Maps to test scenarios module:llsd:test#22-24
- """
- sample_data = [('foo bar magic" go!', b"'foo bar magic\" go!'"),
- ("foo bar magic's go!", b'"foo bar magic\'s go!"'),
- ('have a nice day', b"'have a nice day'"),
- ('have a nice day', b'"have a nice day"'),
- ('have a nice day', b's(15)"have a nice day"'),
- ('have a "nice" day', b'\'have a "nice" day\''),
- ('have a "nice" day', b'"have a \\"nice\\" day"'),
- ('have a "nice" day', b's(17)"have a "nice" day"'),
- ("have a 'nice' day", b"'have a \\'nice\\' day'"),
- ("have a 'nice' day", b'"have a \'nice\' day"'),
- ("have a 'nice' day", b's(17)"have a \'nice\' day"'),
- (u"Kanji: '\u5c0f\u5fc3\u8005'",
- b"'Kanji: \\'\xe5\xb0\x8f\xe5\xbf\x83\xe8\x80\x85\\''"),
- (u"Kanji: '\u5c0f\u5fc3\u8005'",
- b"\"Kanji: '\\xe5\\xb0\\x8f\\xE5\\xbf\\x83\\xe8\\x80\\x85'\""),
- ('\a\b\f\n\r\t\v', b'"\\a\\b\\f\\n\\r\\t\\v"')
- ]
- for py, notation in sample_data:
- is_alternate_notation = False
- if notation[0:1] != "'":
- is_alternate_notation = True
- self.assertNotationRoundtrip(py, notation, is_alternate_notation)
-
- def testURI(self):
- """
- Test the input type: URI.
- Maps to test scenarios module:llsd:test#25 - 26
- """
- uri_tests = {
- llsd.uri('http://www.topcoder.com/tc/projects?id=1230'):b'l"http://www.topcoder.com/tc/projects?id=1230"',
- llsd.uri('http://www.topcoder.com/tc/projects?id=1231'):b"l'http://www.topcoder.com/tc/projects?id=1231'"}
-
- blank_uri_notation = b'l""'
-
- for py, notation in uri_tests.items():
- is_alternate_notation = False
- if notation[1:2] != b'"':
- is_alternate_notation = True
- self.assertNotationRoundtrip(py, notation, is_alternate_notation)
- self.assertEqual('', self.llsd.parse(blank_uri_notation))
-
- def testDate(self):
- """
- Test the input type : Date.
- Maps to test scenarios module:llsd:test#27 - 30
- """
- valid_date_notation = b'd"2006-02-01T14:29:53.460000Z"'
- valid_date_notation_no_float = b'd"2006-02-01T14:29:53Z"'
- valid_date_notation_zero_seconds = b'd"2006-02-01T14:29:00Z"'
- valid_date_notation_filled = b'd"2006-02-01T14:29:05Z"'
- valid_date_19th_century = b'd"1833-02-01T00:00:00Z"'
-
- blank_date_notation = b'd""'
-
- python_valid_date = datetime(2006, 2, 1, 14, 29, 53, 460000)
- python_valid_date_no_float = datetime(2006, 2, 1, 14, 29, 53)
- python_valid_date_zero_seconds = datetime(2006, 2, 1, 14, 29, 0)
- python_valid_date_filled = datetime(2006, 2, 1, 14, 29, 5)
- python_valid_date_19th_century = datetime(1833,2,1)
-
- python_blank_date = datetime(1970, 1, 1)
-
- self.assertNotationRoundtrip(python_valid_date,
- valid_date_notation)
- self.assertNotationRoundtrip(python_valid_date_no_float,
- valid_date_notation_no_float)
- self.assertNotationRoundtrip(python_valid_date_zero_seconds,
- valid_date_notation_zero_seconds)
- self.assertNotationRoundtrip(python_valid_date_filled,
- valid_date_notation_filled)
-
- self.assertNotationRoundtrip(python_valid_date_filled,
- valid_date_notation_filled)
- self.assertNotationRoundtrip(python_valid_date_19th_century,
- valid_date_19th_century)
-
- self.assertEqual(python_blank_date, self.llsd.parse(blank_date_notation))
-
- def testArray(self):
- """
- Test the input type : Array.
- Maps to test scenarios module:llsd:test#31-33
- """
- # simple array
- array_notation = b"['foo', 'bar']"
- # composite array
- array_within_array_notation = b"['foo', 'bar',['foo', 'bar']]"
- # blank array
- blank_array_notation = b"[]"
-
- python_array = [str("foo"), "bar"]
- python_array_within_array = ["foo", "bar", ["foo", "bar"]]
- python_blank_array = []
-
- self.assertNotationRoundtrip(python_array, array_notation)
- self.assertNotationRoundtrip(python_array_within_array,
- array_within_array_notation)
- self.assertNotationRoundtrip(python_blank_array, blank_array_notation)
-
- def testMap(self):
- """
- Test the input type : Map.
- Maps to test scenarios module:llsd:test#34-36
- """
- # simple map
- map_notation = b"{'foo':'bar'}"
-
- # composite map
- map_within_map_notation = b"{'foo':'bar','doo':{'goo':'poo'}}"
-
- # blank map
- blank_map_notation = b"{}"
-
- python_map = {"foo":"bar"}
- python_map_within_map = {"foo":"bar", "doo":{"goo":"poo"}}
- python_blank_map = {}
-
- self.assertNotationRoundtrip(python_map, map_notation)
- self.assertNotationRoundtrip(python_map_within_map,
- map_within_map_notation)
- self.assertNotationRoundtrip(python_blank_map, blank_map_notation)
-
- def testBinary(self):
- """
- Test the input type: binary.
- Maps to test scenarios module:llsd:test#37
- """
- string_data1 = b"quick brown fox!!"
- string_data2 = b"""
- "Take some more tea ," the March Hare said to Alice, very earnestly.
- """
- python_binary1 = llsd.binary(string_data1)
- python_binary2 = llsd.binary(string_data2)
-
- notation1 = b'b64' + b'"' + base64.b64encode(string_data1).strip() + b'"'
- notation2 = b'b64' + b'"' + base64.b64encode(string_data2).strip() + b'"'
- notation3 = b'b16' + b'"' + base64.b16encode(string_data1).strip() + b'"'
- notation4 = b'b16' + b'"' + base64.b16encode(string_data2).strip() + b'"'
- notation5 = b'b85' + b'"<~EHPu*CER),Dg-(AAoDo;+T~>"'
- notation6 = b'b85' +br'"<~4E*J.<+0QR+EMIu4+@0gX@q@26G%G]>+D"u%DImm2Cj@Wq05s)~>"'
-
- self.assertNotationRoundtrip(python_binary1, notation1, True)
- self.assertNotationRoundtrip(python_binary2, notation2, True)
- self.assertNotationRoundtrip(python_binary1, notation3, True)
- self.assertNotationRoundtrip(python_binary2, notation4, True)
- self.assertRaises(llsd.LLSDParseError, self.llsd.parse, notation5)
- self.assertRaises(llsd.LLSDParseError, self.llsd.parse, notation6)
-
- '''
- def testProblemMap(self):
- """
- This is some data that the fuzzer generated that caused a parse error
- """
- string_data = b"{'$g7N':!,'3r=h':true,'\xe8\x88\xbc\xe9\xa7\xb9\xe1\xb9\xa6\xea\xb3\x95\xe0\xa8\xb3\xe1\x9b\x84\xef\xb2\xa7\xe8\x8f\x99\xe8\x94\xa0\xe9\x90\xb9\xe6\x88\x9b\xe0\xaf\x84\xe8\xb8\xa2\xe4\x94\x83\xea\xb5\x8b\xed\x8c\x8a\xe5\xb5\x97':'\xe6\xbb\xa6\xe3\xbf\x88\xea\x9b\x82\xea\x9f\x8d\xee\xbb\xba\xe4\xbf\x87\xe3\x8c\xb5\xe3\xb2\xb0\xe7\x90\x91\xee\x8f\xab\xee\x81\xa5\xea\x94\x98'}"
- python_obj = {}
-
- import pdb; pdb.set_trace()
- self.assertNotationRoundtrip(python_obj, string_data, True)
- '''
-
- def testNotationOfAllTypes(self):
- """
- Test notation with mixed with all kinds of simple types.
- Maps to test scenarios module:llsd:test#38
- """
- python_object = [{'destination': 'http://secondlife.com'}, {'version':
- 1}, {'modification_date': datetime(2006, 2, 1, 14, 29, 53,
- 460000)}, {'first_name': 'Phoenix', 'last_name': 'Linden', 'granters':
- [uuid.UUID('a2e76fcd-9360-4f6d-a924-000000000003')], 'look_at': [-0.043753,
- -0.999042, 0.0], 'attachment_data': [{'attachment_point':
- 2, 'item_id': uuid.UUID('d6852c11-a74e-309a-0462-50533f1ef9b3'),
- 'asset_id': uuid.UUID('c69b29b1-8944-58ae-a7c5-2ca7b23e22fb')},
- {'attachment_point': 10, 'item_id':
- uuid.UUID('ff852c22-a74e-309a-0462-50533f1ef900'), 'asset_id':
- uuid.UUID('5868dd20-c25a-47bd-8b4c-dedc99ef9479')}], 'session_id':
- uuid.UUID('2c585cec-038c-40b0-b42e-a25ebab4d132'), 'agent_id':
- uuid.UUID('3c115e51-04f4-523c-9fa6-98aff1034730'), 'circuit_code': 1075,
- 'position': [70.9247, 254.378,
- 38.7304]}]
-
- notation = b"""[
- {'destination':'http://secondlife.com'},
- {'version':i1},
- {'modification_date':d"2006-02-01T14:29:53.460000Z"}
- {
- 'agent_id':u3c115e51-04f4-523c-9fa6-98aff1034730,
- 'session_id':u2c585cec-038c-40b0-b42e-a25ebab4d132,
- 'circuit_code':i1075,
- 'first_name':'Phoenix',
- 'last_name':'Linden',
- 'position':[r70.9247,r254.378,r38.7304],
- 'look_at':[r-0.043753,r-0.999042,r0.0],
- 'granters':[ua2e76fcd-9360-4f6d-a924-000000000003],
- 'attachment_data':[
- {
- 'attachment_point':i2,
- 'item_id':ud6852c11-a74e-309a-0462-50533f1ef9b3,
- 'asset_id':uc69b29b1-8944-58ae-a7c5-2ca7b23e22fb
- },
- {
- 'attachment_point':i10,
- 'item_id':uff852c22-a74e-309a-0462-50533f1ef900,
- 'asset_id':u5868dd20-c25a-47bd-8b4c-dedc99ef9479
- }
- ]
- }]"""
-
- result = self.llsd.parse(notation)
- self.assertEqual(python_object, result)
-
- # roundtrip test
- notation_result = self.llsd.as_notation(python_object)
- python_object_roundtrip = self.llsd.parse(notation_result)
- self.assertEqual(python_object_roundtrip, python_object)
-
- def testLLSDSerializationFailure(self):
- """
- Test llsd searialization with non supportd object type.
- TypeError should be raised.
-
- Maps test scenarios : module:llsd:test#91
- """
- # make an object not supported by llsd
- python_native_obj = Foo()
-
- # assert than an exception is raised
- self.assertRaises(TypeError, self.llsd.as_notation, python_native_obj)
- self.assertRaises(llsd.LLSDParseError, self.llsd.parse, b'2')
-
- def testParseNotationInvalidNotation1(self):
- """
- Test with an invalid array notation.
- Maps to module:llsd:test#76, 86
- """
- self.assertRaises(llsd.LLSDParseError, self.llsd.parse, b"[ 'foo' : 'bar')")
-
- def testParseNotationInvalidNotation2(self):
- """
- Test with an invalid map notation.
- Maps to module:llsd:test#87
- """
- self.assertRaises(llsd.LLSDParseError, self.llsd.parse, b"{'foo':'bar','doo':{'goo' 'poo'}") # missing separator
- self.assertRaises(llsd.LLSDParseError, self.llsd.parse, b"{'foo':'bar','doo':{'goo' : 'poo'}") # missing closing '}'
-
- def testParseNotationInvalidNotation3(self):
- """
- Test with an invalid map notation.
- Maps to module:llsd:test#88
- """
- self.assertRaises(llsd.LLSDParseError, self.llsd.parse, b"day day up, day day up")
-
- def testParseNotationInvalidNotation4(self):
- """
- Test with an invalid date notation.
- """
- self.assertRaises(llsd.LLSDParseError, self.llsd.parse, b'd"2006#02-01T1429:53.460000Z"')
-
- def testParseNotationInvalidNotation5(self):
- """
- Test with an invalid int notation.
- """
- self.assertRaises(llsd.LLSDParseError, self.llsd.parse, b'i*123xx')
-
- def testParseNotationInvalidNotation6(self):
- """
- Test with an invalid real notation.
- """
- self.assertRaises(llsd.LLSDParseError, self.llsd.parse, b'r**1.23.3434')
-
- def testParseNotationInvalidNotation7(self):
- """
- Test with an invalid binary notation.
- """
- self.assertRaises(llsd.LLSDParseError, self.llsd.parse, b"b634'bGFsYQ='")
-
- def testParseNotationInvalidNotation8(self):
- """
- Test with an invalid map notation.
- """
- self.assertRaises(llsd.LLSDParseError, self.llsd.parse, b"{'foo':'bar',doo':{'goo' 'poo'}}")
-
- def testParseNotationInvalidNotation9(self):
- """
- Test with an invalid map notation.
- """
- self.assertRaises(llsd.LLSDParseError, self.llsd.parse, b"[i123,i123)")
-
- def testParseNotationInvalidNotation10(self):
- """
- Test with an invalid raw string notation.
- """
- self.assertRaises(llsd.LLSDParseError, self.llsd.parse, b"s[2]'xx'")
-
- def testParseNotationInvalidNotation11(self):
- """
- Test with an invalid raw string notation.
- """
- self.assertRaises(llsd.LLSDParseError, self.llsd.parse, b"s(2]'xx'")
-
- def testParseNotationInvalidNotation12(self):
- """
- Test with an invalid raw string notation.
- """
- self.assertRaises(llsd.LLSDParseError, self.llsd.parse, b"s(2)'xxxxx'")
-
- def testParseNotationInvalidNotation13(self):
- """
- Test with an invalid raw string notation.
- """
- self.assertRaises(llsd.LLSDParseError, self.llsd.parse, b"s(2)*xx'")
-
- def testParseNotationIncorrectMIME(self):
- """
- Test with correct notation format but incorrect MIME type. -> llsd:test79
- """
- try:
- self.llsd.parse(b"[ {'foo':'bar'}, {'foo':'bar'} ]", llsd.XML_MIME_TYPE)
- self.fail("LLSDParseError should be raised.")
- except llsd.LLSDParseError:
- pass
-
- def testParseNotationUnterminatedString(self):
- """
- Test with an unterminated delimited string
- """
- self.assertRaises(llsd.LLSDParseError, self.llsd.parse, b"'foo")
-
- def testParseNotationHexEscapeNoChars(self):
- self.assertRaises(llsd.LLSDParseError, self.llsd.parse, b"'\\x")
-
- def testParseNotationHalfTruncatedHex(self):
- self.assertRaises(llsd.LLSDParseError, self.llsd.parse, b"'\\xf")
-
- def testParseNotationInvalidHex(self):
- self.assertRaises(llsd.LLSDParseError, self.llsd.parse, b"'\\xzz'")
-
- def testDeepMap(self):
- """
- Test formatting of a deeply nested map
- """
-
- test_map = {"foo":"bar", "depth":0}
- max_depth = MAX_FORMAT_DEPTH - 1
- for depth in range(max_depth):
- test_map = {"foo":"bar", "depth":depth, "next":test_map}
-
- # this should not throw an exception.
- test_notation_out = self.llsd.as_notation(test_map)
-
- test_notation_parsed = self.llsd.parse(io.BytesIO(test_notation_out))
- self.assertEqual(test_map, test_notation_parsed)
-
- test_map = {"foo":"bar", "depth":depth, "next":test_map}
- # this should throw an exception.
- self.assertRaises(llsd.LLSDSerializationError, self.llsd.as_notation, test_map)
-
-
-class LLSDBinaryUnitTest(unittest.TestCase):
- """
- This class aggregates all the tests for parse_binary and LLSD.as_binary
- which is the same as module function format_binary. The tests use roundtrip
- test to check the serialization of llsd object and the parsing of binary
- representation of llsd object.
-
- Note that llsd binary test scenarios maps to module:llsd:test#66 which reuses
- all the test scenarios of llsd xml.
- """
- def setUp(self):
- """
- Set up the test class, create a LLSD object and assign to self.llsd.
- """
- self.llsd = llsd.LLSD()
-
- def roundTrip(self, something):
- """
- Utility method which serialize the passed in object using
- binary format, parse the serialized binary format into object, and
- return the object.
- """
- binary = self.llsd.as_binary(something)
- frombytes = self.llsd.parse(binary)
- fromstream = self.llsd.parse(io.BytesIO(binary))
- self.assertEqual(fromstream, frombytes)
- return frombytes
-
- def testMap(self):
- """
- Test the binary serialization and parse of llsd type : Map.
- """
- map_xml = b"""\
-
-
-
-foo
-bar
-
- """
-
- map_within_map_xml = b"\
-\
-\
-\
-foo \
-bar \
-doo \
-\
-goo \
-poo \
- \
- \
- "
-
- blank_map_xml = b"\
-\
- \
- "
-
- python_map = {"foo" : "bar"}
- python_map_within_map = {"foo":"bar", "doo":{"goo":"poo"}}
-
- self.assertEqual(python_map, self.roundTrip(self.llsd.parse(map_xml)))
- self.assertEqual(
- python_map_within_map,
- self.roundTrip(self.llsd.parse(map_within_map_xml)))
- self.assertEqual({}, self.roundTrip(self.llsd.parse(blank_map_xml)))
-
- def testArray(self):
- """
- Test the binary serialization and parse of llsd type : Array.
- """
- array_xml = b"\
-\
-\
-\
-foo \
-bar \
- \
- "
- array_within_array_xml = b"\
-\
-\
-\
-foo \
-bar \
-\
-foo \
-bar \
- \
- \
- "
- blank_array_xml = b"\
-\
- \
- "
-
- python_array = ["foo", "bar"]
- python_array_within_array = ["foo", "bar", ["foo", "bar"]]
-
- self.assertEqual(
- python_array,
- self.roundTrip(self.llsd.parse(array_xml)))
- self.assertEqual(
- python_array_within_array,
- self.roundTrip(self.llsd.parse(array_within_array_xml)))
- self.assertEqual(
- [],
- self.roundTrip(self.llsd.parse(blank_array_xml)))
-
- def testString(self):
- """
- Test the binary serialization and parse of llsd type : string.
- """
- normal_xml = b"""
-
-
-foo
- """
-
- blank_xml = b"\
-\
-\
- \
- "
-
- self.assertEqual('foo', self.roundTrip(self.llsd.parse(normal_xml)))
- self.assertEqual("", self.roundTrip(self.llsd.parse(blank_xml)))
-
- def testInteger(self):
- """
- Test the binary serialization and parse of llsd type : integer
- """
- pos_int_xml = b"\
-\
-\
-289343 \
- "
-
- neg_int_xml = b"\
-\
-\
--289343 \
- "
-
- blank_int_xml = b"\
-\
-\
- \
- "
-
- python_pos_int = 289343
- python_neg_int = -289343
-
- self.assertEqual(
- python_pos_int,
- self.roundTrip(self.llsd.parse(pos_int_xml)))
- self.assertEqual(
- python_neg_int,
- self.roundTrip(self.llsd.parse(neg_int_xml)))
- self.assertEqual(
- 0,
- self.roundTrip(self.llsd.parse(blank_int_xml)))
-
- def testReal(self):
- """
- Test the binary serialization and parse of llsd type : real.
- """
- pos_real_xml = b"\
-\
-\
-2983287453.3 \
- "
-
- neg_real_xml = b"\
-\
-\
--2983287453.3 \
- "
-
- blank_real_xml = b"\
-\
-\
- \
- "
-
- python_pos_real = 2983287453.3
- python_neg_real = -2983287453.3
-
- self.assertEqual(
- python_pos_real,
- self.roundTrip(self.llsd.parse(pos_real_xml)))
- self.assertEqual(
- python_neg_real,
- self.roundTrip(self.llsd.parse(neg_real_xml)))
- self.assertEqual(
- 0,
- self.roundTrip(self.llsd.parse(blank_real_xml)))
-
- def testBoolean(self):
- """
- Test the binary serialization and parse of llsd type : boolean.
- """
- true_xml = b"\
-\
-\
-true \
- "
-
- false_xml = b"\
-\
-\
-false \
- "
-
- blank_xml = b"\
-\
-\
- \
- "
-
- self.assertEqual(True, self.roundTrip(self.llsd.parse(true_xml)))
- self.assertEqual(False, self.roundTrip(self.llsd.parse(false_xml)))
- self.assertEqual(False, self.roundTrip(self.llsd.parse(blank_xml)))
-
- def testDate(self):
- """
- Test the binary serialization and parse of llsd type : date.
- """
- valid_date_binary = b"d\x00\x00\x40\x78\x31\xf8\xd0\x41"
- valid_date_xml = b"\
-\
-\
-2006-02-01T14:29:53Z \
- "
-
- blank_date_xml = b"\
-\
-\
- \
- "
- python_valid_date = datetime(2006, 2, 1, 14, 29, 53)
- python_blank_date = datetime(1970, 1, 1)
-
- self.assertEqual(
- python_valid_date,
- self.roundTrip(self.llsd.parse(valid_date_xml)))
- self.assertEqual(
- python_valid_date,
- self.roundTrip(llsd.parse_binary(valid_date_binary)))
- self.assertEqual(
- python_blank_date,
- self.roundTrip(self.llsd.parse(blank_date_xml)))
-
- def testBinary(self):
- """
- Test the binary serialization and parse of llsd type : binary.
- """
- base64_binary_xml = b"\
-\
-\
-dGhlIHF1aWNrIGJyb3duIGZveA== \
- "
-
- foo = self.llsd.parse(base64_binary_xml)
- self.assertEqual(
- llsd.binary(b"the quick brown fox"),
- self.roundTrip(foo))
-
- def testUUID(self):
- """
- Test the binary serialization and parse of llsd type : UUID.
- """
- valid_uuid_xml = b"\
-\
-\
-d7f4aeca-88f1-42a1-b385-b9db18abb255 \
- "
- blank_uuid_xml = b"\
-\
-\
- \
- "
- self.assertEqual(
- 'd7f4aeca-88f1-42a1-b385-b9db18abb255',
- self.roundTrip(str(self.llsd.parse(valid_uuid_xml))))
- self.assertEqual(
- '00000000-0000-0000-0000-000000000000',
- self.roundTrip(str(self.llsd.parse(blank_uuid_xml))))
-
- binary_uuid = b"""\nu\xe1g\xa9D\xd9\x06\x89\x04-\x04\x92\xab\x8e\xaf5\xbf"""
-
- self.assertEqual(uuid.UUID('e167a944-d906-8904-2d04-92ab8eaf35bf'),
- llsd.parse(binary_uuid))
-
- def testURI(self):
- """
- Test the binary serialization and parse of llsd type : URI.
- """
- valid_uri_xml = b"\
-\
-\
-http://sim956.agni.lindenlab.com:12035/runtime/agents \
- "
-
- blank_uri_xml = b"\
-\
-\
- \
- "
-
- self.assertEqual(
- 'http://sim956.agni.lindenlab.com:12035/runtime/agents',
- self.roundTrip(self.llsd.parse(valid_uri_xml)))
- self.assertEqual(
- '',
- self.roundTrip(self.llsd.parse(blank_uri_xml)))
-
- def testUndefined(self):
- """
- Test the binary serialization and parse of llsd type : undef.
- """
- undef_xml = b" "
- self.assertEqual(
- None,
- self.roundTrip(self.llsd.parse(undef_xml)))
-
-
- def testBinaryOfAllTypes(self):
- """
- Test the binary serialization and parse of a composited llsd object
- which is composited of simple llsd types.
- """
- multi_xml = b"\
-\
-\
-\
-\
-\
-content-type application/binary \
- \
-MTIzNDU2Cg== \
- \
-\
-\
-content-type application/exe \
- \
-d2hpbGUoMSkgeyBwcmludCAneWVzJ307Cg== \
- \
- \
- "
-
- multi_python = [
- [{'content-type':'application/binary'},b'123456\n'],
- [{'content-type':'application/exe'},b"while(1) { print 'yes'};\n"]]
-
- self.assertEqual(
- multi_python,
- self.roundTrip(self.llsd.parse(multi_xml)))
-
- def testInvalidBinaryFormat(self):
- """
- Test the parse with an invalid binary format. LLSDParseError should
- be raised.
-
- Maps to test scenarios : module:llsd:test#78
- """
- invalid_binary = b"""\n[\\xx0{}]]"""
-
- self.assertRaises(llsd.LLSDParseError, llsd.parse, invalid_binary)
-
- def testParseBinaryIncorrectMIME(self):
- """
- Test parse with binary format data but has an incorrect MIME type.
-
- LLSDParseError should be raised.
-
- Maps to test scenarios : module:llsd:test#81
- """
- binary_data = b"""\n[\x00\x00\x00\x02i\x00\x00\x00{i\x00\x00\x00{]"""
-
- try:
- llsd.parse(binary_data, llsd.XML_MIME_TYPE)
- self.fail("LLSDParseError should be raised.")
- except llsd.LLSDParseError:
- pass
-
- def testParseBinaryInvlaidBinaryFormat(self):
- """
- Test the parse_binary with an invalid binary format. LLSDParseError
- should be raised.
-
- Maps to test scenario : module:llsd:test#82
- """
- invalid_binary = b"""\n[\\xx0{}]]"""
-
- self.assertRaises(llsd.LLSDParseError, llsd.parse_binary, invalid_binary)
-
- def testAsBinaryWithNonSupportedType(self):
- """
- Test the as_binary with a non-supported python type.
-
- Maps to test scenario module:llsd:test#89
- """
- # make an object not supported by llsd
- python_native_obj = Foo()
-
- # assert than an exception is raised
- self.assertRaises(TypeError, self.llsd.as_binary, python_native_obj)
- self.assertRaises(llsd.LLSDParseError, self.llsd.parse, b'2')
-
- def testInvlaidBinaryParse1(self):
- """
- Test with invalid binary format of map.
- """
- invalid_binary = b"""\n{\x00\x00\x00\x01k\x00\x00\x00\x06'kaka'i\x00\x00\x00{{"""
-
- self.assertRaises(llsd.LLSDParseError, self.llsd.parse, invalid_binary)
-
- def testInvlaidBinaryParse2(self):
- """
- Test with invalid binary format of array.
- """
- invalid_binary = b"""\n[\x00\x00\x00\x02i\x00\x00\x00\x01i\x00\x00\x00\x02*"""
-
- self.assertRaises(llsd.LLSDParseError, self.llsd.parse, invalid_binary)
-
- def testParseDelimitedString(self):
- """
- Test parse_binary with delimited string.
- """
- delimited_string = b"""\n'\\t\\a\\b\\f\\n\\r\\t\\v\\x0f\\p'"""
-
- self.assertEqual('\t\x07\x08\x0c\n\r\t\x0b\x0fp', llsd.parse(delimited_string))
-
- def testDeepMap(self):
- """
- Test formatting of a deeply nested map
- """
-
- test_map = {"foo":"bar", "depth":0}
- max_depth = MAX_FORMAT_DEPTH -1
- for depth in range(max_depth):
- test_map = {"foo":"bar", "depth":depth, "next":test_map}
-
- # this should not throw an exception.
- test_binary_out = self.llsd.as_binary(test_map)
-
- test_binary_parsed = self.llsd.parse(io.BytesIO(test_binary_out))
- self.assertEqual(test_map, test_binary_parsed)
-
- test_map = {"foo":"bar", "depth":depth, "next":test_map}
- # this should throw an exception.
- self.assertRaises(llsd.LLSDSerializationError, self.llsd.as_binary, test_map)
-
-
-
-class LLSDPythonXMLUnitTest(unittest.TestCase):
- """
- This class aggregates all the tests for parse_xml(something), LLSD.as_xml(something)
- and format_xml (i.e. same as LLSD.as_xml(something).
- Note that test scenarios for the same input type are all put into single test method. And utility
- method assert_xml_roundtrip is used to test parse_xml and as_xml at the same time.
-
- NOTE: Tests in this class use the pure python implementation for
- serialization of llsd object to llsd xml format.
- """
- def setUp(self):
- """
- Create a LLSD object
- """
- self.llsd = llsd.LLSD()
-
- def assertXMLRoundtrip(self, py, xml, ignore_rounding=False):
- """
- Utility method to test parse_xml and as_xml at the same time
- """
-
- # use parse to check
- parsed_py = self.llsd.parse(xml)
- parsed_stream = self.llsd.parse(io.BytesIO(xml))
- self.assertEqual(parsed_stream, parsed_py)
- formatted_xml = self.llsd.as_xml(py)
- self.assertEqual(parsed_py, py)
- self.assertEqual(py, self.llsd.parse(formatted_xml))
-## if not ignore_rounding:
-## self.assertEqual(self.strip(formatted_xml),
-## self.strip(xml))
-## self.assertEqual(self.strip(xml),
-## self.strip(self.llsd.as_xml(parsed_py)))
-
- # use parse_xml to check again
- parsed_py = llsd.parse_xml(xml)
- formatted_xml = self.llsd.as_xml(py)
- self.assertEqual(parsed_py, py)
- self.assertEqual(py, llsd.parse_xml(formatted_xml))
-## if not ignore_rounding:
-## self.assertEqual(self.strip(formatted_xml),
-## self.strip(xml))
-## self.assertEqual(self.strip(xml),
-## self.strip(self.llsd.as_xml(parsed_py)))
-
- def testBytesConversion(self):
- """
- Test the __bytes__() conversion on the LLSD class
- """
- if PY2:
- return # not applicable on python 2
- some_xml =b"\
-\
-\
-1234 \
- "
-
- c = llsd.LLSD(llsd.parse_xml(some_xml))
- out_xml = bytes(c)
-
- self.assertEqual(some_xml, out_xml)
-
- def testStrConversion(self):
- """
- Test the __str__() conversion on the LLSD class
- """
- some_xml =b"\
-\
-\
-1234 \
- "
-
- c = llsd.LLSD(llsd.parse_xml(some_xml))
- out_xml = str(c).encode()
-
- self.assertEqual(some_xml, out_xml)
-
- def testInteger(self):
- """
- Test the parse and serializatioin of input type : integer
- Maps to the test scenarios : module:llsd:test#39 - 41
- """
- pos_int_xml = b"\
-\
-\
-289343 \
- "
-
- neg_int_xml = b"\
-\
-\
--289343 \
- "
-
- blank_int_xml = b"\
-\
-\
- \
- "
-
- python_pos_int = 289343
- python_neg_int = -289343
- python_blank_int = 0
-
- self.assertXMLRoundtrip(python_pos_int,
- pos_int_xml)
- self.assertXMLRoundtrip(python_neg_int,
- neg_int_xml)
- self.assertEqual(python_blank_int, self.llsd.parse(blank_int_xml))
-
- def testUndefined(self):
- """
- Test the parse and serialization of input type: undef
-
- Maps to test scenarios module:llsd:test#42
- """
- undef_xml = b" "
- self.assertXMLRoundtrip(None, undef_xml)
-
- def testBoolean(self):
- """
- Test the parse and serialization of input tye: boolean. -> llsd:test 43 - 45
- """
- true_xml = b"\
-\
-\
-true \
- "
-
- false_xml = b"\
-\
-\
-false \
- "
-
- blank_xml = b"\
-\
-\
- \
- "
-
- self.assertXMLRoundtrip(True, true_xml)
- self.assertXMLRoundtrip(False, false_xml)
- self.assertEqual(False, self.llsd.parse(blank_xml))
-
- def testReal(self):
- """
- Test the parse and serialization of input type : real.
- Maps to test scenarios module:llsd:test# 46 - 48
- """
- pos_real_xml = b"\
-\
-\
-2983287453.3000002 \
- "
-
- neg_real_xml = b"\
-\
-\
--2983287453.3000002 \
- "
-
- blank_real_xml = b"\
-\
-\
- \
- "
-
- python_pos_real = 2983287453.3
- python_neg_real = -2983287453.3
- python_blank_real = 0.0
-
- self.assertXMLRoundtrip(python_pos_real,
- pos_real_xml, True)
- self.assertXMLRoundtrip(python_neg_real,
- neg_real_xml, True)
- self.assertEqual(python_blank_real, self.llsd.parse(blank_real_xml))
-
- def testUUID(self):
- """
- Test the parse and serialization of input type: UUID.
- Maps to test scenarios module:llsd:test#49
- """
- uuid_tests = {
- uuid.UUID(hex='d7f4aeca-88f1-42a1-b385-b9db18abb255'):b"\
-\
-\
-d7f4aeca-88f1-42a1-b385-b9db18abb255 \
- ",
- uuid.UUID(int=0):b"\
-\
-\
- \
- "}
-
- for py, xml in uuid_tests.items():
- self.assertXMLRoundtrip(py, xml)
-
-
- def testString(self):
- """
- Test the parse and serialization of input type : String.
- Maps to test scenarios module:llsd:test# 50 - 51
- """
- sample_data = {'foo':b"\
-\
-\
-foo \
- ",
- '':b"\
-\
-\
- \
- ",
- '&ent; ':b"\
-\
-\
-<xml>&ent;</xml> \
- "
- }
- for py, xml in sample_data.items():
- self.assertXMLRoundtrip(py, xml)
-
- def testURI(self):
- """
- Test the parse and serialization of input type: URI.
- Maps to test scenarios module:llsd:test# 52 - 53
- """
- uri_tests = {
- llsd.uri('http://sim956.agni.lindenlab.com:12035/runtime/agents'):b"\
-\
-\
-http://sim956.agni.lindenlab.com:12035/runtime/agents \
- "}
-
- blank_uri_xml = b"\
-\
-\
- \
- "
-
- for py, xml in uri_tests.items():
- self.assertXMLRoundtrip(py, xml)
- self.assertEqual('', self.llsd.parse(blank_uri_xml))
-
- def testDate(self):
- """
- Test the parse and serialization of input type : Date.
- Maps to test scenarios module:llsd:test#54 - 57
- """
- valid_date_xml = b"\
-\
-\
-2006-02-01T14:29:53.460000Z \
- "
-
- valid_date_xml_no_fractional = b"\
-\
-\
-2006-02-01T14:29:53Z \
- "
- valid_date_xml_filled = b"\
-\
-\
-2006-02-01T14:29:05Z \
- "
-
- blank_date_xml = b"\
-\
-\
- \
- "
-
- before_19th_century_date = b"\
-\
-\
-1853-02-01T00:00:00Z \
- "
-
- python_valid_date = datetime(2006, 2, 1, 14, 29, 53, 460000)
- python_valid_date_no_fractional = datetime(2006, 2, 1, 14, 29, 53)
- python_valid_date_filled = datetime(2006, 2, 1, 14, 29, 5)
- python_blank_date = datetime(1970, 1, 1)
- python_19th_century_date = datetime(1853, 2, 1)
- self.assertXMLRoundtrip(python_valid_date,
- valid_date_xml)
- self.assertXMLRoundtrip(python_valid_date_no_fractional,
- valid_date_xml_no_fractional)
- self.assertXMLRoundtrip(python_valid_date_filled,
- valid_date_xml_filled)
- self.assertXMLRoundtrip(python_19th_century_date,
- before_19th_century_date)
- self.assertEqual(python_blank_date, self.llsd.parse(blank_date_xml))
-
- def testArray(self):
- """
- Test the parse and serialization of input type : Array.
- Maps to test scenarios module:llsd:test# 58 - 60
- """
- # simple array
- array_xml = b"\
-\
-\
-\
-foo \
-bar \
- \
- "
- # composite array
- array_within_array_xml = b"\
-\
-\
-\
-foo \
-bar \
-\
-foo \
-bar \
- \
- \
- "
- # blank array
- blank_array_xml = b"\
-\
-\
- \
- "
-
- python_array = ["foo", "bar"]
- python_array_within_array = ["foo", "bar", ["foo", "bar"]]
-
- self.assertXMLRoundtrip(python_array, array_xml)
- self.assertXMLRoundtrip(python_array_within_array,
- array_within_array_xml)
- self.assertXMLRoundtrip([], blank_array_xml)
-
- def testMap(self):
- """
- Test the parse and serialization of input type : map.
- Maps to test scenarios module:llsd:test# 61 - 63
- """
- # simple map
- map_xml = b"""\
-
-
-
-foo
-bar
-
- """
- # composite map
- map_within_map_xml = b"\
-\
-\
-\
-foo \
-bar \
-doo \
-\
-goo \
-poo \
- \
- \
- "
- # blank map
- blank_map_xml = b"\
-\
-\
- \
- "
-
- python_map = {"foo":"bar"}
- python_map_within_map = {"foo":"bar", "doo":{"goo":"poo"}}
-
- self.assertXMLRoundtrip(python_map, map_xml)
- self.assertXMLRoundtrip(python_map_within_map,
- map_within_map_xml)
- self.assertXMLRoundtrip({}, blank_map_xml)
-
- def testBinary(self):
- """
- Test the parse and serialization of input type : binary.
- Maps to test scenarios module:llsd:test#64
- """
- base64_binary_xml = b"\
-\
-\
-dGhlIHF1aWNrIGJyb3duIGZveA== \
- "
-
- python_binary = llsd.binary(b"the quick brown fox")
- self.assertXMLRoundtrip(python_binary,
- base64_binary_xml)
-
- blank_binary_xml = b""" """
-
- python_binary = llsd.binary(b'');
-
- self.assertXMLRoundtrip(python_binary, blank_binary_xml)
-
- @pytest.mark.skipif(PY2, reason="Object order between python 2 and 3 differs")
- def testViewerAutobuildRoundTrip(self):
- """Test that llsd does not muck up the viewer autobuild"""
- with open(path.join(FIXTURES_DIR, "viewer-autobuild.xml"), "rb") as f:
- autobuild_bytes = f.read()
- autobuild_parsed = llsd.parse_xml(autobuild_bytes)
- assert autobuild_bytes.decode("utf8") == llsd.format_pretty_xml(autobuild_parsed).decode("utf8")
-
-
- def testXMLOfAllTypes(self):
- """
- Test parse_xml with complex xml data which contains all types xml element.
- Maps to test scenarios module:llsd:test#65
- """
- xml_of_all_types = b"""
-
-
- string1
- 3.1415
- 18686
-
- www.topcoder.com/tc
- 2006-02-01T14:29:53.43Z
-
- region_id
- 67153d5b-3659-afb4-8510-adda2c034649
- scale
- one minute
- simulator statistics
-
- time dilation
- 0.9878624
- sim fps
- 44.38898
- pysics fps
- 44.38906
- agent updates per second
- 1.34
- lsl instructions per second
- 0
- total task count
- 4
- active task count
- 0
- active script count
- 4
- main agent count
- 0
- child agent count
- 0
- inbound packets per second
- 1.228283
- outbound packets per second
- 1.277508
- pending downloads
- 0
- pending uploads
- 0.0001096525
- frame ms
- 0.7757886
- net ms
- 0.3152919
- sim other ms
- 0.1826937
- sim physics ms
- 0.04323055
- agent ms
- 0.01599029
- image ms
- 0.01865955
- script ms
- 0.1338836
-
-
-
- """
-
- python_object = ['string1', 3.1415, 18686, None,
- 'www.topcoder.com/tc', datetime(2006, 2, 1, 14, 29, 53, 430000),
- {'scale': 'one minute', 'region_id':
- uuid.UUID('67153d5b-3659-afb4-8510-adda2c034649'),
- 'simulator statistics': {'total task count': 4.0, 'active task count': 0.0,
- 'time dilation': 0.9878624, 'lsl instructions per second': 0.0, 'frame ms':
- 0.7757886, 'agent ms': 0.01599029, 'sim other ms': 0.1826937,
- 'pysics fps': 44.38906, 'outbound packets per second': 1.277508,
- 'pending downloads': 0.0, 'pending uploads': 0.0001096525, 'net ms': 0.3152919,
- 'agent updates per second': 1.34, 'inbound packets per second':
- 1.228283, 'script ms': 0.1338836, 'main agent count': 0.0,
- 'active script count': 4.0, 'image ms': 0.01865955, 'sim physics ms':
- 0.04323055, 'child agent count': 0.0, 'sim fps': 44.38898}}]
-
- parsed_python = llsd.parse(xml_of_all_types)
-
- self.assertEqual(python_object, parsed_python)
-
- def testFormatPrettyXML(self):
- """
- Test the format_pretty_xml function, characters like \n,\t should be generated within
- the output to beautify the output xml.
-
- This maps to test scenarios module:llsd:test#75
- """
- python_object = {'id': ['string1', 123, {'name': 123}]}
-
- output_xml = llsd.format_pretty_xml(python_object)
-
- with open("foo.llsd.xml", "wb") as f:
- f.write(output_xml)
-
- self.assertEqual(output_xml.decode("utf8"), """
-
-
- id
-
- string1
- 123
-
- name
- 123
-
-
-
-
-""")
-
- # check whether the output_xml contains whitespaces and new line character
- whitespaces_count = output_xml.count(b' ')
- newline_count = output_xml.count(b'\n')
-
- self.assertTrue(whitespaces_count > 50)
- self.assertTrue(newline_count > 10)
-
- # remove all the whitespaces and new line chars from output_xml
- result = self.strip(output_xml)
-
- # the result should equal to the reuslt of format_xml
- # the xml version tag should be removed before comparing
- format_xml_result = self.llsd.as_xml(python_object)
- self.assertEqual(result[result.find(b"?>") + 2: len(result)],
- format_xml_result[format_xml_result.find(b"?>") + 2: len(format_xml_result)])
-
- def testDeepMap(self):
- """
- Test formatting of a deeply nested map
- """
-
- test_map = {"foo":"bar", "depth":0}
- max_depth = MAX_FORMAT_DEPTH - 1
- for depth in range(max_depth):
- test_map = {"foo":"bar", "depth":depth, "next":test_map}
-
- # this should not throw an exception.
- test_xml_out = self.llsd.as_xml(test_map)
-
- test_xml_parsed = self.llsd.parse(io.BytesIO(test_xml_out))
- self.assertEqual(test_map, test_xml_parsed)
-
- test_map = {"foo":"bar", "depth":depth, "next":test_map}
- # this should throw an exception.
- self.assertRaises(llsd.LLSDSerializationError, self.llsd.as_xml, test_map)
-
- def testLLSDSerializationFailure(self):
- """
- Test serialization function as_xml with an object of non-supported type.
- TypeError should be raised.
-
- This maps test scenarios module:llsd:test#90
- """
- # make an object not supported by llsd
- python_native_obj = Foo()
-
- # assert than an exception is raised
- self.assertRaises(TypeError, self.llsd.as_xml, python_native_obj)
-
- def testParseXMLIncorrectMIME(self):
- """
- Test parse function with llsd in xml format but with incorrect mime type.
-
- Maps to test scenario module:llsd:test#80
- """
- llsd_xml = b"""12.3232 """
-
- try:
- self.llsd.parse(llsd_xml, llsd.NOTATION_MIME_TYPE)
- self.fail("LLSDParseError should be raised.")
- except llsd.LLSDParseError:
- pass
-
- def testParseXMLIncorrectMIME2(self):
- """
- Test parse function with llsd in xml format but with incorrect mime type.
-
- Maps to test scenario module:llsd:test#80
- """
- llsd_xml = b"""12.3232 """
-
- try:
- self.llsd.parse(llsd_xml, llsd.BINARY_MIME_TYPE)
- self.fail("LLSDParseError should be raised.")
- except llsd.LLSDParseError:
- pass
-
- def testParseMalformedXML(self):
- """
- Test parse with malformed llsd xml. LLSDParseError should be raised.
-
- Maps to test scenarios module:llsd:test#77
- """
- malformed_xml = b"""string>123/llsd>"""
- self.assertRaises(llsd.LLSDParseError, llsd.parse, malformed_xml)
-
- def testParseXMLUnsupportedTag(self):
- """
- Test parse with llsd xml which has non-supported tag. LLSDParseError
- should be raised.
-
- Maps to test scenario module:llsd:test#83
- """
- unsupported_tag_xml = b"""123
- 1 /llsd>"""
- self.assertRaises(llsd.LLSDParseError, llsd.parse, unsupported_tag_xml)
-
- def testParseXMLWithoutRootTag(self):
- """
- Test parse with xml which does not have root tag .
- LLSDParseError should be raised.
-
- Maps to test scenario module:llsd:test#84
- """
- no_root_tag_xml = b"""test 1.3434 """
-
- self.assertRaises(llsd.LLSDParseError, llsd.parse, no_root_tag_xml)
-
- def testParseXMLUnclosedTag(self):
- """
- Test parse with xml which has unclosed tag.
- LLSDParseError should be raised.
-
- Maps to test scenario module:llsd:test#85
- """
- unclosed_tag_xml = b"""123
- 12345/llsd>"""
- self.assertRaises(llsd.LLSDParseError, llsd.parse, unclosed_tag_xml)
-
- def strip(self, the_string):
- """
- Utility method to remove all the whitespace characters from
- the given string.
- """
- return re.sub(br'\s', b'', the_string)
-
- def test_segfault(self):
- for i, badstring in enumerate([
- b'',
- b'',
- b'',
- b'',
- b'',
- b'',
- b'']):
- self.assertRaises(llsd.LLSDParseError, llsd.parse, badstring)
-
-class LLSDStressTest(unittest.TestCase):
- """
- This class aggregates all the stress tests for llsd.
- """
-
- # python object used for testing
- python_object = [{'destination': 'http://secondlife.com'}, {'version':
- 1}, {'modification_date': datetime(2006, 2, 1, 14, 29, 53,
- 460000)}, {'first_name': 'Phoenix', 'last_name': 'Linden', 'granters':
- [uuid.UUID('a2e76fcd-9360-4f6d-a924-000000000003')], 'look_at': [-0.043753,
- -0.999042, 0.0], 'attachment_data': [{'attachment_point':
- 2, 'item_id': uuid.UUID('d6852c11-a74e-309a-0462-50533f1ef9b3'),
- 'asset_id': uuid.UUID('c69b29b1-8944-58ae-a7c5-2ca7b23e22fb')},
- {'attachment_point': 10, 'item_id':
- uuid.UUID('ff852c22-a74e-309a-0462-50533f1ef900'), 'asset_id':
- uuid.UUID('5868dd20-c25a-47bd-8b4c-dedc99ef9479')}], 'session_id':
- uuid.UUID('2c585cec-038c-40b0-b42e-a25ebab4d132'), 'agent_id':
- uuid.UUID('3c115e51-04f4-523c-9fa6-98aff1034730'), 'circuit_code': 1075,
- 'position': [70.9247, 254.378,
- 38.7304]}]
-
- # how many times to run
- number = 5000
-
- def testParseAndFormatXMLStress(self):
- """
- Stress test for parse_xml and as_xml.
-
- Maps to test scenraio module:llsd:test#95
- """
- t = time.time()
- for i in range(0, self.number):
- x = llsd.format_xml(self.python_object)
- delta = time.time() - t
- print("format_xml", str(self.number), " times takes total :", delta, "secs")
- print("average time:", delta / self.number, "secs")
-
- t = time.time()
- for i in range(0, self.number):
- r = llsd.parse(x)
- delta = time.time() - t
- print("parse_xml", str(self.number), " times takes total :", delta, "secs")
- print("average time:", delta / self.number, "secs")
-
-
- def testParseAndFormatNotationStress(self):
- """
- Stress test for parse_notation and as_notation.
-
- Maps to test scenario module:llsd:test#96
- """
- t = time.time()
- for i in range(0, self.number):
- x = llsd.format_notation(self.python_object)
- delta = time.time() - t
- print("format_notation", str(self.number), " times takes total :", delta, "secs")
- print("average time:", delta / self.number, "secs")
-
- t = time.time()
- for i in range(0, self.number):
- r = llsd.parse(x)
- delta = time.time() - t
- print("parse_notation", str(self.number), " times takes total :", delta, "secs")
- print("average time:", delta / self.number, "secs")
-
- def testParseAndFormatBinaryStress(self):
- """
- Stress test for parse_binary and as_binary.
-
- Maps to test scenarios module:llsd:test#97,98
- """
- t = time.time()
- for i in range(0, self.number):
- x = llsd.format_binary(self.python_object)
- delta = time.time() - t
- print("format_binary", str(self.number), " times takes total :", delta, "secs")
- print("average time:", delta / self.number, "secs")
-
- t = time.time()
- for i in range(0, self.number):
- r = llsd.parse(x)
- delta = time.time() - t
- print("parse_binary", str(self.number), " times takes total :", delta, "secs")
- print("average time:", delta / self.number, "secs")
-
-
-FUZZ_ITERATIONS = 5000
-class LLSDFuzzTest(unittest.TestCase):
- """
- This class aggregates all the fuzz tests for llsd.
- """
- python_object = LLSDStressTest.python_object
- def assertEqualsPretty(self, a, b):
- try:
- self.assertEqual(a,b)
- except AssertionError:
- self.fail("\n%s\n !=\n%s" % (pprint.pformat(a), pprint.pformat(b)))
-
- def fuzz_parsing_base(self, fuzz_method_name, legit_exceptions):
- fuzzer = LLSDFuzzer(seed=1234)
- fuzz_method = getattr(fuzzer, fuzz_method_name)
- for f in islice(fuzz_method(self.python_object), FUZZ_ITERATIONS):
- try:
- parsed = llsd.parse(f)
- except legit_exceptions:
- pass # expected, since many of the inputs will be invalid
- except Exception as e:
- print("Raised exception", e.__class__)
- print("Fuzzed value was", repr(f))
- raise
-
- def fuzz_roundtrip_base(self, formatter_method, normalize=None):
- fuzzer = LLSDFuzzer(seed=1234)
- for f in islice(fuzzer.structure_fuzz(self.python_object), FUZZ_ITERATIONS):
- try:
- try:
- text = formatter_method(f)
- except llsd.LLSDSerializationError:
- # sometimes the fuzzer will generate invalid llsd
- continue
- parsed = llsd.parse(text)
- try:
- self.assertEqualsPretty(parsed, f)
- except AssertionError:
- if normalize:
- self.assertEqualsPretty(normalize(parsed), normalize(f))
- else:
- raise
- except llsd.LLSDParseError:
- print("Failed to parse", repr(text))
- raise
-
-
- def test_notation_parsing(self):
- self.fuzz_parsing_base('notation_fuzz',
- (llsd.LLSDParseError, IndexError, ValueError))
-
- def test_notation_roundtrip(self):
- def normalize(s):
- """ Certain transformations of input data are permitted by
- the spec; this function normalizes a python data structure
- so it receives these transformations as well.
- * date objects -> datetime objects (parser only produces datetimes)
- * nan converted to None (just because nan's are incomparable)
- """
- if is_string(s):
- return s
- if isnan(s):
- return None
- if isinstance(s, date):
- return datetime(s.year, s.month, s.day)
- if isinstance(s, (list, tuple)):
- s = [normalize(x) for x in s]
- if isinstance(s, dict):
- s = dict([(normalize(k), normalize(v))
- for k,v in s.items()])
- return s
-
- self.fuzz_roundtrip_base(llsd.format_notation, normalize)
-
- def test_binary_parsing(self):
- self.fuzz_parsing_base('binary_fuzz',
- (llsd.LLSDParseError, IndexError, ValueError))
-
- def test_binary_roundtrip(self):
- def normalize(s):
- """ Certain transformations of input data are permitted by
- the spec; this function normalizes a python data structure
- so it receives these transformations as well.
- * date objects -> datetime objects (parser only produces datetimes)
- * fractional seconds dropped from datetime objects
- * integral values larger than a signed 32-bit int become wrapped
- * integral values larger than an unsigned 32-bit int become 0
- * nan converted to None (just because nan's are incomparable)
- """
- if isnan(s):
- return None
- if is_integer(s):
- if (s > (2<<30) - 1 or
- s < -(2<<30)):
- return struct.unpack('!i', struct.pack('!i', s))[0]
- if isinstance(s, date):
- return datetime(s.year, s.month, s.day)
- if isinstance(s, datetime):
- return datetime(s.year, s.month, s.day, s.hour, s.minute, s.second)
- if isinstance(s, (list, tuple)):
- s = [normalize(x) for x in s]
- if isinstance(s, dict):
- s = dict([(normalize(k), normalize(v))
- for k,v in s.items()])
- return s
- self.fuzz_roundtrip_base(llsd.format_binary, normalize)
-
- def test_xml_parsing(self):
- self.fuzz_parsing_base('xml_fuzz',
- (llsd.LLSDParseError, IndexError, ValueError))
-
- newline_re = re.compile(r'[\r\n]+')
-
- @pytest.mark.skipif(PY2, reason="Fails because fuzz generates invalid unicode sequences on Python 2")
- def test_xml_roundtrip(self):
- def normalize(s):
- """ Certain transformations of input data are permitted by
- the spec; this function normalizes a python data structure
- so it receives these transformations as well.
- * codepoints disallowed in xml dropped from strings and unicode objects
- * any sequence of \n and \r compressed into a single \n
- * date objects -> datetime objects (parser only produces datetimes)
- * nan converted to None (just because nan's are incomparable)
- """
- if is_string(s):
- s = remove_invalid_xml_bytes(s)
- s = self.newline_re.sub('\n', s)
- if is_unicode(s):
- s = s.replace(u'\uffff', u'')
- s = s.replace(u'\ufffe', u'')
- return s
- if isnan(s):
- return None
- if isinstance(s, date):
- return datetime(s.year, s.month, s.day)
- if isinstance(s, (list, tuple)):
- s = [normalize(x) for x in s]
- if isinstance(s, dict):
- s = dict([(normalize(k), normalize(v))
- for k,v in s.items()])
- return s
- self.fuzz_roundtrip_base(llsd.format_xml, normalize)
-
-class Regression(unittest.TestCase):
- '''
- Regression tests.
- '''
-
- def test_no_newline_in_base64_notation(self):
- n = llsd.format_notation(llsd.binary(b'\0'*100))
- self.assertEqual(n.replace(b'\n', b''), n)
-
- def test_no_newline_in_base64_xml(self):
- n = llsd.format_xml(llsd.binary(b'\0'*100))
- self.assertEqual(n.replace(b'\n', b''), n)
-
- def test_SL_13073(self):
- # "new note" in Russian with Cyrillic characters.
- good_xml = u'ΠΠΎΠ²Π°Ρ Π·Π°ΠΌΠ΅ΡΠΊΠ° '.encode('utf8')
- new_note_unicode = u"ΠΠΎΠ²Π°Ρ Π·Π°ΠΌΠ΅ΡΠΊΠ°"
- new_note_str = "ΠΠΎΠ²Π°Ρ Π·Π°ΠΌΠ΅ΡΠΊΠ°"
-
- # Py2 unicode
- # Py3 str (unicode)
- self.assertEqual(llsd.format_xml(new_note_unicode), good_xml)
-
- # Py2 LLSD(unicode)
- # Py3 LLSD(str (unicode))
- self.assertEqual(llsd.format_xml(llsd.LLSD(new_note_unicode)), good_xml)
-
- # Py2 str (b"")
- # Py3 str (unicode)
- self.assertEqual(llsd.format_xml(new_note_str), good_xml)
-
- # Py2 LLSD(str (b""))
- # Py3 LLSD(str (unicode))
- self.assertEqual(llsd.format_xml(llsd.LLSD(new_note_str)), good_xml)
-
- if PY2:
- bytes_xml = good_xml
- else:
- bytes_xml = b'0J3QvtCy0LDRjyDQt9Cw0LzQtdGC0LrQsA== '
- # Py2 str (b"")
- # Py3 bytes (turned into binary type by llsd)
- self.assertEqual(llsd.format_xml(new_note_unicode.encode("utf-8")), bytes_xml)
-
- # Py2 LLSD(str (b""))
- # Py3 LLSD(bytes) (turned into binary type by llsd)
- self.assertEqual(llsd.format_xml(llsd.LLSD(new_note_unicode.encode("utf-8"))), bytes_xml)
-
-class MapConstraints(unittest.TestCase):
- '''
- Implied type conversion tests
- '''
-
- def test_int_map_key(self):
- '''
- LLSD Map keys are supposed to be strings; convert a map with an int key
- '''
- llsdmap=llsd.LLSD({5 : 'int'})
- self.assertEqual(llsd.format_xml(llsdmap), b'5 int ')
- self.assertEqual(llsd.format_notation(llsdmap), b"{'5':'int'}")
-
- def test_date_map_key(self):
- '''
- LLSD Map keys are supposed to be strings; convert a map with a date key
- '''
- llsdmap=llsd.LLSD({datetime(2006, 2, 1, 14, 29, 53, 460000) : 'date'})
- self.assertEqual(llsd.format_xml(llsdmap), b'2006-02-01 14:29:53.460000 date ')
- self.assertEqual(llsd.format_notation(llsdmap), b"{'2006-02-01 14:29:53.460000':'date'}")
-
- def test_uuid_map_key(self):
- '''
- LLSD Map keys are supposed to be strings; convert a map with a uuid key
- '''
- llsdmap=llsd.LLSD({uuid.UUID(int=0) : 'uuid'})
- self.assertEqual(llsd.format_xml(llsdmap), b'00000000-0000-0000-0000-000000000000 uuid ')
- self.assertEqual(llsd.format_notation(llsdmap), b"{'00000000-0000-0000-0000-000000000000':'uuid'}")
-
-
diff --git a/tox.ini b/tox.ini
deleted file mode 100644
index 2af420c..0000000
--- a/tox.ini
+++ /dev/null
@@ -1,8 +0,0 @@
-[tox]
-envlist = py27, py37, py38, py310
-
-[testenv]
-setenv =
- COVERAGE_FILE = .coverage.{envname}
-deps = .[dev]
-commands = pytest -vv --cov=llsd --cov-report=xml:.coverage.{envname}.xml tests/