structlog-17.2.0/ 0000755 0000765 0000024 00000000000 13106347161 014072 5 ustar hynek staff 0000000 0000000 structlog-17.2.0/.coveragerc 0000644 0000765 0000024 00000000274 12610175427 016221 0 ustar hynek staff 0000000 0000000 [run]
branch = True
source = structlog
[paths]
source =
src/structlog
.tox/*/lib/python*/site-packages/structlog
.tox/pypy*/site-packages/structlog
[report]
show_missing = True
structlog-17.2.0/.travis.yml 0000644 0000765 0000024 00000002106 13077354071 016207 0 ustar hynek staff 0000000 0000000 sudo: false
cache:
directories:
- $HOME/.cache/pip
language: python
matrix:
include:
- python: "2.7"
env: TOXENV=py27-threads
- python: "2.7"
env: TOXENV=py27-greenlets
- python: "3.4"
env: TOXENV=py34-threads
- python: "3.4"
env: TOXENV=py34-greenlets
- python: "3.5"
env: TOXENV=py35-threads
- python: "3.5"
env: TOXENV=py35-greenlets
- python: "3.6"
env: TOXENV=py36-threads
- python: "3.6"
env: TOXENV=py36-greenlets
- python: "pypy"
env: TOXENV=pypy-threads
- python: "pypy"
env: TOXENV=pypy-greenlets
- python: "2.7"
env: TOXENV=py27-colorama
- python: "3.6"
env: TOXENV=py36-colorama
# Meta
- python: "3.6"
env: TOXENV=flake8
- python: "3.6"
env: TOXENV=manifest
- python: "3.6"
env: TOXENV=docs
- python: "3.6"
env: TOXENV=readme
install:
- pip install tox
script:
- tox
before_install:
- pip install codecov
after_success:
- tox -e coverage-report
- codecov
notifications:
email: false
structlog-17.2.0/AUTHORS.rst 0000644 0000765 0000024 00000001155 13100107646 015747 0 ustar hynek staff 0000000 0000000 Authors
=======
``structlog`` is written and maintained by `Hynek Schlawack `_.
It’s inspired by previous work done by `Jean-Paul Calderone `_ and `David Reid `_.
The development is kindly supported by `Variomedia AG `_.
A full list of contributors can be found on GitHub’s `overview `_.
Some of them disapprove of the addition of thread local context data. :)
The ``structlog`` logo has been contributed by `Russell Keith-Magee `_.
structlog-17.2.0/CHANGELOG.rst 0000644 0000765 0000024 00000027024 13106345064 016120 0 ustar hynek staff 0000000 0000000 Changelog
=========
Versions are year-based with a strict backward compatibility policy.
The third digit is only for regressions.
17.2.0 (2017-05-15)
-------------------
Backward-incompatible changes:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
*none*
Deprecations:
^^^^^^^^^^^^^
*none*
Changes:
^^^^^^^^
- ``structlog.stdlib.ProcessorFormatter`` now accepts *keep_exc_info* and *keep_stack_info* arguments to control what to do with this information on log records.
Most likely you want them both to be ``False`` therefore it's the default.
`#109 `_
- ``structlog.stdlib.add_logger_name()`` now works in ``structlog.stdlib.ProcessorFormatter``'s ``foreign_pre_chain``.
`#112 `_
- Clear log record args in ``structlog.stdlib.ProcessorFormatter`` after rendering.
This fix is for you if you tried to use it and got ``TypeError: not all arguments converted during string formatting`` exceptions.
`#116 `_
`#117 `_
----
17.1.0 (2017-04-24)
-------------------
The main features of this release are massive improvements in standard library's ``logging`` integration.
Have a look at the updated `standard library chapter `_ on how to use them!
Special thanks go to
`Fabian Büchler `_,
`Gilbert Gilb's `_,
`Iva Kaneva `_,
`insolite `_,
and `sky-code `_,
that made them possible.
Backward-incompatible changes:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- The default renderer now is ``structlog.dev.ConsoleRenderer`` if you don't configure ``structlog``.
Colors are used if available and human-friendly timestamps are prepended.
This is in line with our backward `compatibility policy `_ that explicitly excludes default settings.
Changes:
^^^^^^^^
- Added ``structlog.stdlib.render_to_log_kwargs()``.
This allows you to use ``logging``-based formatters to take care of rendering your entries.
`#98 `_
- Added ``structlog.stdlib.ProcessorFormatter`` which does the opposite:
This allows you to run ``structlog`` processors on arbitrary ``logging.LogRecords``.
`#79 `_
`#105 `_
- UNIX epoch timestamps from ``structlog.processors.TimeStamper`` are more precise now.
- Added *repr_native_str* to ``structlog.processors.KeyValueRenderer`` and ``structlog.dev.ConsoleRenderer``.
This allows for human-readable non-ASCII output on Python 2 (``repr()`` on Python 2 behaves like ``ascii()`` on Python 3 in that regard).
As per compatibility policy, it's on (original behavior) in ``KeyValueRenderer`` and off (humand-friendly behavior) in ``ConsoleRenderer``.
`#94 `_
- Added *colors* argument to ``structlog.dev.ConsoleRenderer`` and made it the default renderer.
`#78 `_
- Fixed bug with Python 3 and ``structlog.stdlib.BoundLogger.log()``.
Error log level was not reproductible and was logged as exception one time out of two.
`#92 `_
- Positional arguments are now removed even if they are empty.
`#82 `_
----
16.1.0 (2016-05-24)
-------------------
Backward-incompatible changes:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Python 3.3 and 2.6 aren't supported anymore.
They may work by chance but any effort to keep them working has ceased.
The last Python 2.6 release was on October 29, 2013 and isn't supported by the CPython core team anymore.
Major Python packages like Django and Twisted dropped Python 2.6 a while ago already.
Python 3.3 never had a significant user base and wasn't part of any distribution's LTS release.
Changes:
^^^^^^^^
- Add a ``drop_missing`` argument to ``KeyValueRenderer``.
If ``key_order`` is used and a key is missing a value, it's not rendered at all instead of being rendered as ``None``.
`#67 `_
- Exceptions without a ``__traceback__`` are now also rendered on Python 3.
- Don't cache loggers in lazy proxies returned from ``get_logger()``.
This lead to in-place mutation of them if used before configuration which in turn lead to the problem that configuration was applied only partially to them later.
`#72 `_
----
16.0.0 (2016-01-28)
-------------------
Changes:
^^^^^^^^
- ``structlog.processors.ExceptionPrettyPrinter`` and ``structlog.processors.format_exc_info`` now support passing of Exceptions on Python 3.
- Clean up the context when exiting ``structlog.threadlocal.tmp_bind`` in case of exceptions.
`#64 `_
- Be more more lenient about missing ``__name__``\ s.
`#62 `_
- Add ``structlog.dev.ConsoleRenderer`` that renders the event dictionary aligned and with colors.
- Use `six `_ for compatibility.
- Add ``structlog.processors.UnicodeDecoder`` that will decode all byte string values in an event dictionary to Unicode.
- Add ``serializer`` parameter to ``structlog.processors.JSONRenderer`` which allows for using different (possibly faster) JSON encoders than the standard library.
----
15.3.0 (2015-09-25)
-------------------
Changes:
^^^^^^^^
- Tolerate frames without a ``__name__``, better.
`#58 `_
- Officially support Python 3.5.
- Add ``structlog.ReturnLogger.failure`` and ``structlog.PrintLogger.failure`` as preparation for the new Twisted logging system.
----
15.2.0 (2015-06-10)
-------------------
Changes:
^^^^^^^^
- Allow empty lists of processors.
This is a valid use case since `#26 `_ has been merged.
Before, supplying an empty list resulted in the defaults being used.
- Prevent Twisted's ``log.err`` from quoting strings rendered by ``structlog.twisted.JSONRenderer``.
- Better support of ``logging.Logger.exception`` within ``structlog``.
`#52 `_
- Add option to specify target key in ``structlog.processors.TimeStamper`` processor.
`#51 `_
----
15.1.0 (2015-02-24)
-------------------
Changes:
^^^^^^^^
- Tolerate frames without a ``__name__``.
----
15.0.0 (2015-01-23)
-------------------
Changes:
^^^^^^^^
- Add ``structlog.stdlib.add_log_level`` and ``structlog.stdlib.add_logger_name`` processors.
`#44 `_
- Add ``structlog.stdlib.BoundLogger.log``.
`#42 `_
- Pass positional arguments to stdlib wrapped loggers that use string formatting.
`#19 `_
- ``structlog`` is now dually licensed under the `Apache License, Version 2 `_ and the `MIT `_ license.
Therefore it is now legal to use structlog with `GPLv2 `_-licensed projects.
`#28 `_
- Add ``structlog.stdlib.BoundLogger.exception``.
`#22 `_
----
0.4.2 (2014-07-26)
------------------
Changes:
^^^^^^^^
- Fixed a memory leak in greenlet code that emulates thread locals.
It shouldn't matter in practice unless you use multiple wrapped dicts within one program that is rather unlikely.
`#8 `_
- ``structlog.PrintLogger`` now is thread-safe.
- Test Twisted-related code on Python 3 (with some caveats).
- Drop support for Python 3.2.
There is no justification to add complexity for a Python version that nobody uses.
If you are one of the `0.350% `_ that use Python 3.2, please stick to the 0.4 branch; critical bugs will still be fixed.
- Officially support Python 3.4.
- Allow final processor to return a dictionary.
See the adapting chapter.
`#26`_
- ``from structlog import *`` works now (but you still shouldn't use it).
----
0.4.1 (2013-12-19)
------------------
Changes:
^^^^^^^^
- Don't cache proxied methods in ``structlog.threadlocal._ThreadLocalDictWrapper``.
This doesn't affect regular users.
- Various doc fixes.
----
0.4.0 (2013-11-10)
------------------
Backward-incompatible changes:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Changes:
^^^^^^^^
- Add ``structlog.processors.StackInfoRenderer`` for adding stack information to log entries without involving exceptions.
Also added it to default processor chain.
`#6 `_
- Allow optional positional arguments for ``structlog.get_logger`` that are passed to logger factories.
The standard library factory uses this for explicit logger naming.
`#12 `_
- Add ``structlog.processors.ExceptionPrettyPrinter`` for development and testing when multiline log entries aren't just acceptable but even helpful.
- Allow the standard library name guesser to ignore certain frame names.
This is useful together with frameworks.
- Add meta data (e.g. function names, line numbers) extraction for wrapped stdlib loggers.
`#5 `_
----
0.3.2 (2013-09-27)
------------------
Changes:
^^^^^^^^
- Fix stdlib's name guessing.
----
0.3.1 (2013-09-26)
------------------
Changes:
^^^^^^^^
- Add forgotten ``structlog.processors.TimeStamper`` to API documentation.
----
0.3.0 (2013-09-23)
------------------
Changes:
^^^^^^^^
- Greatly enhanced and polished the documentation and added a new theme based on Write The Docs, requests, and Flask.
- Add Python Standard Library-specific BoundLogger that has an explicit API instead of intercepting unknown method calls.
See ``structlog.stdlib.BoundLogger``.
- ``structlog.ReturnLogger`` now allows arbitrary positional and keyword arguments.
- Add Twisted-specific BoundLogger that has an explicit API instead of intercepting unknown method calls.
See ``structlog.twisted.BoundLogger``.
- Allow logger proxies that are returned by ``structlog.get_logger`` and ``structlog.wrap_logger`` to cache the BoundLogger they assemble according to configuration on first use.
See the chapter on performance and the ``cache_logger_on_first_use`` argument of ``structlog.configure`` and ``structlog.wrap_logger``.
- Extract a common base class for loggers that does nothing except keeping the context state.
This makes writing custom loggers much easier and more straight-forward.
See ``structlog.BoundLoggerBase``.
----
0.2.0 (2013-09-17)
------------------
Changes:
^^^^^^^^
- Promote to stable, thus henceforth a strict backward compatibility policy is put into effect.
- Add ``key_order`` option to ``structlog.processors.KeyValueRenderer`` for more predictable log entries with any ``dict`` class.
- ``structlog.PrintLogger`` now uses proper I/O routines and is thus viable not only for examples but also for production.
- Enhance Twisted support by offering JSONification of non-structlog log entries.
- Allow for custom serialization in ``structlog.twisted.JSONRenderer`` without abusing ``__repr__``.
----
0.1.0 (2013-09-16)
------------------
Initial release.
structlog-17.2.0/CODE_OF_CONDUCT.rst 0000644 0000765 0000024 00000006223 12653614205 017106 0 ustar hynek staff 0000000 0000000 Contributor Covenant Code of Conduct
====================================
Our Pledge
----------
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
Our Standards
-------------
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
Our Responsibilities
--------------------
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
Scope
-----
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community.
Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
Representation of a project may be further defined and clarified by project maintainers.
Enforcement
-----------
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at hs@ox.cx.
all complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances.
The project team is obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
Attribution
-----------
This Code of Conduct is adapted from the `Contributor Covenant `_, version 1.4, available at http://contributor-covenant.org/version/1/4.
structlog-17.2.0/conftest.py 0000644 0000765 0000024 00000001301 13057215454 016270 0 ustar hynek staff 0000000 0000000 # -*- coding: utf-8 -*-
# This file is dual licensed under the terms of the Apache License, Version
# 2.0, and the MIT License. See the LICENSE file in the root of this
# repository for complete details.
from __future__ import absolute_import, division, print_function
import pytest
from six.moves import cStringIO as StringIO
@pytest.fixture
def sio():
"""
A StringIO instance.
"""
return StringIO()
@pytest.fixture
def event_dict():
"""
An example event dictionary with multiple value types w/o the event itself.
"""
class A(object):
def __repr__(self):
return ""
return {"a": A(), "b": [3, 4], "x": 7, "y": "test", "z": (1, 2)}
structlog-17.2.0/CONTRIBUTING.rst 0000644 0000765 0000024 00000013255 13077360377 016554 0 ustar hynek staff 0000000 0000000 How To Contribute
=================
First off, thank you for considering contributing to ``structlog``!
It's people like *you* who make it is such a great tool for everyone.
This document is mainly to help you to get started by codifying tribal knowledge and expectations and make it more accessible to everyone.
But don't be afraid to open half-finished PRs and ask questions if something is unclear!
Workflow
--------
- No contribution is too small!
Please submit as many fixes for typos and grammar bloopers as you can!
- Try to limit each pull request to *one* change only.
- *Always* add tests and docs for your code.
This is a hard rule; patches with missing tests or documentation can't be accepted.
- Make sure your changes pass our CI_.
You won't get any feedback until it's green unless you ask for it.
- Once you've addressed review feedback, make sure to bump the pull request with a short note.
Maintainers don’t receive notifications when you push new commits.
- Don’t break `backward compatibility`_.
Code
----
- Obey `PEP 8`_ and `PEP 257`_.
We use the ``"""``\ -on-separate-lines style for docstrings:
.. code-block:: python
def func(x):
"""
Do something.
:param str x: A very important parameter.
:rtype: str
"""
- If you add or change public APIs, tag the docstring using ``.. versionadded:: 16.0.0 WHAT`` or ``.. versionchanged:: 17.1.0 WHAT``.
- Prefer double quotes (``"``) over single quotes (``'``) unless the string contains double quotes itself.
Tests
-----
- Write your asserts as ``expected == actual`` to line them up nicely:
.. code-block:: python
x = f()
assert 42 == x.some_attribute
assert "foo" == x._a_private_attribute
- To run the test suite, all you need is a recent tox_.
It will ensure the test suite runs with all dependencies against all Python versions just as it will on Travis CI.
If you lack some Python versions, you can can always limit the environments like ``tox -e py27,py35`` (in that case you may want to look into pyenv_, which makes it very easy to install many different Python versions in parallel).
- Write `good test docstrings`_.
Documentation
-------------
- Use `semantic newlines`_ in reStructuredText_ files (files ending in ``.rst``):
.. code-block:: rst
This is a sentence.
This is another sentence.
- If you start a new section, add two blank lines before and one blank line after the header except if two headers follow immediately after each other:
.. code-block:: rst
Last line of previous section.
Header of New Top Section
-------------------------
Header of New Section
^^^^^^^^^^^^^^^^^^^^^
First line of new section.
- If your change is noteworthy, add an entry to the changelog_.
Use `semantic newlines`_, and add a link to your pull request:
.. code-block:: rst
- Added ``structlog.func()`` that does foo.
It's pretty cool.
[`#1 `_]
- ``structlog.func()`` now doesn't crash the Large Hadron Collider anymore.
That was a nasty bug!
[`#2 `_]
Local Development Environment
-----------------------------
You can (and should) run our test suite using tox_ however you’ll probably want a more traditional environment too.
We highly recommend to develop using the latest Python 3 release because you're more likely to catch certain bugs earlier.
First create a `virtual environment `_.
It’s out of scope for this document to list all the ways to manage virtual environments in Python but if you don’t have already a pet way, take some time to look at tools like `pew `_, `virtualfish `_, and `virtualenvwrapper `_.
Next get an up to date checkout of the ``structlog`` repository:
.. code-block:: bash
git checkout git@github.com:hynek/structlog.git
Change into the newly created directory and **after activating your virtual environment** install an editable version of ``structlog``:
.. code-block:: bash
cd structlog
pip install -e .
If you run the virtual environment’s Python and try to ``import structlog`` it should work!
To run the test suite, you'll need our development dependencies which can be installed using
.. code-block:: bash
pip install -r dev-requirements.txt
At this point
.. code-block:: bash
python -m pytest
should work and pass!
****
Again, this list is mainly to help you to get started by codifying tribal knowledge and expectations.
If something is unclear, feel free to ask for help!
Please note that this project is released with a Contributor `Code of Conduct`_.
By participating in this project you agree to abide by its terms.
Please report any harm to `Hynek Schlawack`_ in any way you find appropriate.
Thank you for considering contributing to ``structlog``!
.. _`Hynek Schlawack`: https://hynek.me/about/
.. _`PEP 8`: https://www.python.org/dev/peps/pep-0008/
.. _`PEP 257`: https://www.python.org/dev/peps/pep-0257/
.. _`good test docstrings`: https://jml.io/pages/test-docstrings.html
.. _`Code of Conduct`: https://github.com/hynek/structlog/blob/master/CODE_OF_CONDUCT.rst
.. _changelog: https://github.com/hynek/structlog/blob/master/CHANGELOG.rst
.. _`backward compatibility`: https://structlog.readthedocs.io/en/latest/backward-compatibility.html
.. _tox: https://tox.readthedocs.io/
.. _pyenv: https://github.com/pyenv/pyenv
.. _reStructuredText: http://sphinx-doc.org/rest.html
.. _semantic newlines: http://rhodesmill.org/brandon/2012/one-sentence-per-line/
.. _CI: https://travis-ci.org/hynek/structlog/
structlog-17.2.0/dev-requirements.txt 0000644 0000765 0000024 00000000071 13075361575 020142 0 ustar hynek staff 0000000 0000000 -e .
coverage
freezegun>=0.2.8
pretend
pytest
simplejson
structlog-17.2.0/docs/ 0000755 0000765 0000024 00000000000 13106347161 015022 5 ustar hynek staff 0000000 0000000 structlog-17.2.0/docs/_static/ 0000755 0000765 0000024 00000000000 13106347161 016450 5 ustar hynek staff 0000000 0000000 structlog-17.2.0/docs/_static/.keep 0000644 0000765 0000024 00000000000 12204213705 017355 0 ustar hynek staff 0000000 0000000 structlog-17.2.0/docs/_static/console_renderer.png 0000644 0000765 0000024 00000234136 12635326216 022523 0 ustar hynek staff 0000000 0000000 PNG
IHDR g ^- sRGB @ IDATx]\T{Qi@l{"Ě苦GhgIkPAQ"ET鰔ݻV(?s9sL ?.pppppppppppnu}nj
hbwí6ϭBPvЬGW~um$""k[x{s4TwwP_69mۯnO<(UFѫ/jyڜLU!} /(cEgܮQ)LY5~-+eVa.Rҵi|_ܶ,Q֟LD@
#eđ$,|FM@j|{/(v fs1]A.5eUt==8
Nf)k'a~?;/WlvU~c#_F~`F_Wp(JцY?Ov0V8,{(Bۗ`ދ"Ǥ _=?4V:/ֶ VWie6Ju寯eOYMa3W:];=kA\`cQ\{<Ժz7\'O @!JE芪
W$ik׀!hLlU+C4, v?Rȁh5N*(fBRLbPFRdZ@/,ʍTCRUfsU30Ga|DѹbR%9tX]9I+>q
ݒp,e4 quJOx,/CeA&3Լ6Mi&~4IkE~ngXTQFۑwFSC1.%*SP7܅լn`L8胩S/DZ|dž"W
c}#6)*hL>XwtqF8EO^ Ņ1T#P81MO;
5L
1b^X_o(Pno`!z
g\̜Xl|u` ~5,l'0t'"Tr!'
w@HuUkieUJ #0ҠJ#ɫҁT?9f=L+'i$wi|Q\"Fs
D@DZw#zf֬j3z7p`oFgؽ3K~')J`C#/qSV jx
5>{sPo<.DbvU*;A3aNFºs*UJK wRL>YU5,N7af(lFѸUk>*{0}T˵<;4L!:^=b%VH++k,&J'
^&>9kߍLңx
ܲYd&W'߫I.bD"cgNEC?caTXV}^.W?8\4pd,v>*GQl$g9G2$W"//%*QK'}rQ]&@PSY^LDߟGiceކ][OOcE_I\.G<_"͛{|ecwFK
֣=9R3OSJ6B:H+r.ۿ`qX7!yjCgJ3Y~'^V~%ӂ3X6@_댟\> &7n?3ؾkk6b
ti'Hlw0O"[~)\%mrojMRFL(OEjSe$9D|H uJ꘨T?@mLYv$+%y _;>ҥV..q'q >h kd(+vL镴,E8y2MF˱)ƫ
u|[!?Mj]{e
!ЯUBhjTI/ %%sQ_MVn?qn^0>ZWK~zM)S0}tLh`Jmビ1[aE1F;P-9l,f
6+]˴}=[cgNGHg C+̬h8Kn[vOQ865n":op 67&ፈ|=cҍ1nQ[ݲ;;іo+ْ9+[#XXYxc=F%cBf;~ְt1Zz}\?sǏX*(07xw
붜B#1zKZAkT"OrE貕p@*Og>c8IJ8k<E_Ⱦ78EN ̤_".EYً+^mV
|/;dǯ{0uWt}3c<(k(KШ7{y^GmP%.Dn@0o#=&lYnSi041Ay_&F i/HI؇̋x*7ըbX( G;*mz!fsf<Y';C"l?bYd>@QHl`Ld.)"V*'4GA HĭXUd&4hW+~4@Z>{Zսn#QmJn,*4CLJ\{Bf/%Y}1L϶d
"fA^"VcPXx
7_O+IO`Ҽ
\maP[^V(vl%4: 6f|doàqp˿?($>ɭ_PJK7Oנ5uK`Wa0jWAG%nkGdn!!tuenGvNCпQ"}5.5pKº,</cM)98h'glC3p-ǀov z[<ʾҍp~_LOT
g
t>/$;=4M&:i\~a_!cM:G7[ T|O_MP{F/o