From 8954c78f6f17207d887480b7a0a550a3dfd50dec Mon Sep 17 00:00:00 2001 From: willtheorangeguy <18339050+willtheorangeguy@users.noreply.github.com> Date: Tue, 18 Aug 2026 18:40:52 -0600 Subject: [PATCH 1/2] docs: rewrite README and docs/ (includes a trademark question needing your decision) Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01TtaJBmFDK3GcSyuhSuZ84R --- README.md | 130 +++++++------------------- docs/CUSTOMIZATION.md | 41 -------- docs/README.md | 72 +++++++++++--- docs/USAGE.md | 84 ----------------- docs/api.md | 83 ++++++++++++++++ docs/architecture.md | 91 ++++++++++++++++++ docs/configuration.md | 63 +++++++++++++ docs/development.md | 73 +++++++++++++++ docs/faq.md | 74 +++++++++++++++ docs/images/logo.png | Bin 14278 -> 0 bytes docs/images/pythonlogo.png | Bin 45544 -> 0 bytes docs/images/pythonpoweredheight.png | Bin 29888 -> 0 bytes docs/images/pythonpoweredwidth.png | Bin 15445 -> 0 bytes docs/installation.md | 67 +++++++++++++ docs/internal/known-issues.md | 61 ++++++++++++ docs/legal/{PRIVACY.md => privacy.md} | 0 docs/legal/{TERMS.md => terms.md} | 0 docs/quickstart.md | 70 ++++++++++++++ docs/roadmap.md | 57 +++++++++++ docs/troubleshooting.md | 97 +++++++++++++++++++ 20 files changed, 831 insertions(+), 232 deletions(-) delete mode 100644 docs/CUSTOMIZATION.md delete mode 100644 docs/USAGE.md create mode 100644 docs/api.md create mode 100644 docs/architecture.md create mode 100644 docs/configuration.md create mode 100644 docs/development.md create mode 100644 docs/faq.md delete mode 100644 docs/images/logo.png delete mode 100644 docs/images/pythonlogo.png delete mode 100644 docs/images/pythonpoweredheight.png delete mode 100644 docs/images/pythonpoweredwidth.png create mode 100644 docs/installation.md create mode 100644 docs/internal/known-issues.md rename docs/legal/{PRIVACY.md => privacy.md} (100%) rename docs/legal/{TERMS.md => terms.md} (100%) create mode 100644 docs/quickstart.md create mode 100644 docs/roadmap.md create mode 100644 docs/troubleshooting.md diff --git a/README.md b/README.md index d4af61b..20c1b35 100644 --- a/README.md +++ b/README.md @@ -1,144 +1,90 @@

- Python Logo Widgets + Python Logo Widgets
Python Logo Widgets

-

A group of widgets showing the Python logos, that can easily be added to your Python GUI code!

+

Drop-in Tkinter widgets for the Python logo and the "Python Powered" badges.

- - PyPI Build State - - PyTest State - - Pylint State - - CodeQL State - - Gitleaks State - - GitHub Version - + GitHub Version GitHub Issues - GitHub Pull Requests - - Discord Server ID - - Downloads - - GitHub Languages + License

Key Features • - Download • - How To Use • + Installation • + Usage • + DocumentationSupportContributing • - Changelog • - Credits & Contributors + Credits • + License

- Python Logo Widget - Python Powered Height Widget - Python Powered Width Widget + Python Logo Widget + Python Powered Height Widget + Python Powered Width Widget
## Key Features -* High quality images. -* Easy to integrate into a `Tkinter` GUI project. -* Embeddable `tkinter.Frame` widgets — use them in your own windows. -* Standalone demo mode. -* Installable via `pip`. -* Cross platform. +- Three embeddable `tkinter.Frame` subclasses — put them straight into your own windows. +- Images bundled with the package and resolved through `importlib.resources`, so they work however you install it. +- Each widget keeps its own image reference, so nothing renders blank. +- A standalone demo, and backward-compatible wrappers for the original function API. +- Pure standard library — Tkinter only. +- Cross-platform. -## Download - -You can **[download](https://github.com/willtheorangeguy/Python-Logo-Widgets/releases/latest) the source code** to run the scripts from the command line on Windows, macOS and Linux. **This will require [Python](https://www.python.org/downloads/).** - -## How To Use - -### Install +## Installation ```bash pip install Python-Logo-Widgets ``` -### Embed in Your Application +## Usage ```python import tkinter as tk -from python_logo_widgets import LogoWidget, PoweredByLengthWidget, PoweredByWidthWidget +from python_logo_widgets import LogoWidget, PoweredByWidthWidget root = tk.Tk() -root.title("My App") - -# Add any combination of widgets to your window LogoWidget(root, bg="white").pack(pady=10) PoweredByWidthWidget(root).pack(side=tk.BOTTOM) - root.mainloop() ``` -Available widgets: - -| Widget Class | Image | +| Widget | Image | |---|---| -| `LogoWidget` | Python logo | -| `PoweredByLengthWidget` | "Python Powered" tall badge | -| `PoweredByWidthWidget` | "Python Powered" wide badge | +| `LogoWidget` | The Python logo | +| `PoweredByLengthWidget` | "Python Powered", tall | +| `PoweredByWidthWidget` | "Python Powered", wide | -Each widget accepts a `parent` widget and an optional `bg` parameter (default `"black"`). +Each takes a parent and an optional `bg` (default `"black"`). Demo: `python-logo-widgets` or `python -m python_logo_widgets`. -### Run the Demo +## Documentation -```bash -# Via the command line entry point -python-logo-widgets - -# Or as a module -python -m python_logo_widgets -``` - -### Git (Development) - -```bash -# Clone this repository -$ git clone https://github.com/willtheorangeguy/Python-Logo-Widgets - -# Go into the repository -$ cd Python-Logo-Widgets - -# Install in development mode -$ pip install -e . - -# Run the demo -$ python -m python_logo_widgets -``` +Full documentation lives in [`docs/`](docs/README.md): +[Quickstart](docs/quickstart.md) · [Installation](docs/installation.md) · [Configuration](docs/configuration.md) · [Architecture](docs/architecture.md) · [API](docs/api.md) · [Development](docs/development.md) · [FAQ](docs/faq.md) · [Troubleshooting](docs/troubleshooting.md) · [Roadmap](docs/roadmap.md) ## Support -Customizing the logo and widget sizes can be found in [`CUSTOMIZATION`](https://github.com/willtheorangeguy/Python-Logo-Widgets/blob/master/docs/CUSTOMIZATION.md). Hard-coding the widgets into your project can be found in [`USAGE`](https://github.com/willtheorangeguy/Python-Logo-Widgets/blob/master/docs/USAGE.md). More documentation is available in the **[Documentation](https://github.com/willtheorangeguy/Python-Logo-Widgets/tree/main/docs)** and on the **[Wiki](https://github.com/willtheorangeguy/Python-Logo-Widgets/wiki)**. If more support is required, please open a **[GitHub Discussion](https://github.com/willtheorangeguy/Python-Logo-Widgets/discussions/new)** or join our **[Discord](https://discord.gg/eAZZJzhHrW)**. +Open a [GitHub Discussion](https://github.com/willtheorangeguy/Python-Logo-Widgets/discussions/new), file an [issue](https://github.com/willtheorangeguy/Python-Logo-Widgets/issues/new/choose), or join the [Discord](https://discord.gg/eAZZJzhHrW). ## Contributing Please contribute using [GitHub Flow](https://guides.github.com/introduction/flow). Create a branch, add commits, and [open a pull request](https://github.com/willtheorangeguy/Python-Logo-Widgets/compare). -Please read [`CONTRIBUTING`](https://github.com/willtheorangeguy/.github/blob/main/CONTRIBUTING.md) for details on our [`CODE OF CONDUCT`](https://github.com/willtheorangeguy/.github/blob/main/CODE_OF_CONDUCT.md), and the process for submitting pull requests to us. - -## Changelog - -See the [`CHANGELOG`](CHANGELOG.md) file for details. +See the org-wide [Contributing Guide](https://github.com/willtheorangeguy/.github/blob/main/CONTRIBUTING.md) and [Code of Conduct](https://github.com/willtheorangeguy/.github/blob/main/CODE_OF_CONDUCT.md). ## Credits @@ -162,16 +108,12 @@ This software uses the following open source packages, projects, services or web Web - Donate -## Contributors - -* [@willtheorangeguy](https://github.com/willtheorangeguy) - Sponsor on [PayPal](https://paypal.me/wvdg44?country.x=CA&locale.x=en_US) +Sponsor [@willtheorangeguy](https://github.com/willtheorangeguy) on [PayPal](https://paypal.me/wvdg44?country.x=CA&locale.x=en_US). -## You may also like... +## License -* [Running Calculator](https://github.com/willtheorangeguy/Running-Calculator) - A running speed calculator for any unit of distance. -* [PyWorkout](https://github.com/willtheorangeguy/PyWorkout) - A minimal CLI to keep you inspired during your workout! -* [PyAvatar](https://github.com/willtheorangeguy/PyAvatar) - Easily display all of your creative avatars to keep them consistent across websites. +The **code** is licensed under the [GNU General Public License v3](https://www.gnu.org/licenses/gpl-3.0.en.html) — see [`LICENSE.md`](LICENSE.md). -## License +The **images** are the Python logo and the "Python Powered" badges, which are trademarks of the [Python Software Foundation](https://www.python.org/psf/trademarks/) and are not the author's to license. Their use is governed by the PSF Trademark Usage Policy, not by the licence above — see [`docs/internal/known-issues.md`](docs/internal/known-issues.md), which records this as needing a decision. -This project is licensed under the [GNU General Public License](https://www.gnu.org/licenses/gpl-3.0.en.html) - see the [`LICENSE`](LICENSE.md) file for details. See the [Privacy Policy](https://github.com/willtheorangeguy/Python-Logo-Widgets/blob/master/docs/legal/PRIVACY.md) and [Terms and Conditions](https://github.com/willtheorangeguy/Python-Logo-Widgets/blob/master/docs/legal/TERMS.md) for legal information. +[Privacy Policy](docs/legal/privacy.md) · [Terms and Conditions](docs/legal/terms.md) diff --git a/docs/CUSTOMIZATION.md b/docs/CUSTOMIZATION.md deleted file mode 100644 index 2c86da5..0000000 --- a/docs/CUSTOMIZATION.md +++ /dev/null @@ -1,41 +0,0 @@ -# Python Logo Widgets Customization - -## Change Background Color - -Pass the `bg` parameter when creating a widget: - -```python -from python_logo_widgets import LogoWidget - -# White background -LogoWidget(root, bg="white").pack() - -# Custom hex color -LogoWidget(root, bg="#2b2b2b").pack() -``` - -## Pass Additional Frame Options - -All extra keyword arguments are passed through to `tk.Frame`: - -```python -LogoWidget(root, bg="white", padx=10, pady=10, relief="raised", borderwidth=2).pack() -``` - -## Change Image - -To use a custom image, subclass the widget and override the image path: - -```python -import tkinter as tk -from python_logo_widgets.widgets import _load_image - -class CustomLogoWidget(tk.Frame): - def __init__(self, parent, bg="black", **kwargs): - super().__init__(parent, **kwargs) - self._image = tk.PhotoImage(file="path/to/your/image.gif") - self._label = tk.Label(self, image=self._image, bg=bg) - self._label.pack(fill=tk.BOTH, expand=True) -``` - -**Note:** `tkinter.PhotoImage` supports `.gif` and `.png` formats. diff --git a/docs/README.md b/docs/README.md index e6ba192..ca45271 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,14 +1,60 @@ -# Python Logo Widgets Documentation - -This folder includes all of the docs for the Python Logo Widgets. More can be found on the [wiki](https://github.com/willtheorangeguy/Python-Logo-Widgets/wiki). - -```text -├── docs -| ├── images -| ├── legal -| | ├── PRIVACY.md -| | ├── TERMS.md -| ├── USAGE.md -| ├── CUSTOMIZATION.md -└── README.md +# Python Logo Widgets — Documentation + +Three Tkinter `Frame` subclasses that display the Python logo and the "Python Powered" badges, +with the images bundled so you do not have to ship them yourself. + ``` +python_logo_widgets/ +├── widgets.py LogoWidget, PoweredByLengthWidget, PoweredByWidthWidget +├── _compat.py the original function API, kept working +├── _demo.py the standalone demo +├── __main__.py python -m python_logo_widgets +└── imgs/ logo.gif, length.gif, width.gif +``` + +## Pages + +- [Quickstart](./quickstart.md) — embed one in five lines +- [Installation](./installation.md) — pip, or from source +- [Configuration](./configuration.md) — the `bg` argument and sizing +- [Architecture](./architecture.md) — how the images are found and kept alive +- [API](./api.md) — the three classes and the compatibility functions +- [Development](./development.md) — tests and conventions +- [FAQ](./faq.md) — trademarks, sizing, why GIF +- [Troubleshooting](./troubleshooting.md) — blank widgets, missing images +- [Roadmap](./roadmap.md) — direction and non-goals +- [Known issues](./internal/known-issues.md) — recorded defects + +## Before you redistribute this + +The images are **PSF trademarks**, not GPL-licensed content. + +The repository's `LICENSE.md` is GPL v3, which grants recipients the right to modify and +redistribute everything it covers. The Python logo and the "Python Powered" badges are trademarks +of the Python Software Foundation, governed by the +[PSF Trademark Usage Policy](https://www.python.org/psf/trademarks/) — they are not the author's +to place under GPL, and the policy restricts modifying them in ways the GPL explicitly permits. + +Using the badges to indicate that your software is built with Python is the use the PSF intends. +Treating the image files as GPL content you may alter and redistribute is not. + +Recorded in [`internal/known-issues.md`](./internal/known-issues.md) as needing an owner +decision. Nothing here has been changed. + +## The legal documents + +`docs/legal/PRIVACY.md` and `docs/legal/TERMS.md` are generated boilerplate describing accounts, +personal data collection, and "the Service". This package has none of those — it opens no +network connection, stores nothing, and reads only its own bundled images. + +Same known-issues file. + +## What it actually does + +Loads three GIFs from the installed package and puts each in a `Label` inside a `Frame`. That is +the whole implementation, and it is about seventy lines. + +The value is in the details it gets right: resources resolved through `importlib.resources` so +they are found however the package is installed, and each image bound to `self._image` so Tkinter +cannot garbage-collect it out from under the label. Both are covered in +[Architecture](./architecture.md). diff --git a/docs/USAGE.md b/docs/USAGE.md deleted file mode 100644 index 2c9e30c..0000000 --- a/docs/USAGE.md +++ /dev/null @@ -1,84 +0,0 @@ -# Python Logo Widgets Usage - -## Install via `pip` - -```bash -pip install Python-Logo-Widgets -``` - -## Embed in Your Application - -Import the widget classes and add them to your `tkinter` window: - -```python -import tkinter as tk -from python_logo_widgets import LogoWidget, PoweredByLengthWidget, PoweredByWidthWidget - -root = tk.Tk() -root.title("My Application") - -# Add any combination of widgets -logo = LogoWidget(root, bg="white") -logo.pack(pady=10) - -powered = PoweredByWidthWidget(root) -powered.pack(side=tk.BOTTOM) - -root.mainloop() -``` - -### Available Widgets - -| Widget Class | Image | Description | -|---|---|---| -| `LogoWidget` | `logo.gif` | The Python logo | -| `PoweredByLengthWidget` | `length.gif` | "Python Powered" tall badge | -| `PoweredByWidthWidget` | `width.gif` | "Python Powered" wide badge | - -### Parameters - -All widgets accept: - -- **`parent`** — The parent `tkinter` widget (required). -- **`bg`** — Background color for the image label (default: `"black"`). -- **`**kwargs`** — Any additional keyword arguments are passed to `tk.Frame`. - -### Layout - -The widgets are `tkinter.Frame` subclasses, so you can use any geometry manager: - -```python -# Using pack -LogoWidget(root).pack(side=tk.TOP, pady=5) - -# Using grid -LogoWidget(root).grid(row=0, column=0, padx=10) - -# Using place -LogoWidget(root).place(x=50, y=50) -``` - -## Standalone Demo - -To see all three widgets in a demo window: - -```bash -# Command line -python-logo-widgets - -# As a module -python -m python_logo_widgets -``` - -## Legacy Standalone Functions - -For backward compatibility, the old standalone functions are still available: - -```python -from python_logo_widgets import logo_widget, length_widget, width_widget - -# Each opens its own window with mainloop() -logo_widget() -``` - -These create their own `Tk()` root window and call `mainloop()`, so they cannot be embedded in an existing application. diff --git a/docs/api.md b/docs/api.md new file mode 100644 index 0000000..38c199a --- /dev/null +++ b/docs/api.md @@ -0,0 +1,83 @@ +# Python Logo Widgets — API + +## Widget classes + +All three subclass `tkinter.Frame` and share a signature. + +```python +LogoWidget(parent, bg="black", **kwargs) +PoweredByLengthWidget(parent, bg="black", **kwargs) +PoweredByWidthWidget(parent, bg="black", **kwargs) +``` + +| Parameter | Meaning | +|---|---| +| `parent` | The parent Tkinter widget | +| `bg` | Background of the inner image label; default `"black"` | +| `**kwargs` | Forwarded to `tk.Frame` | + +| Class | Image | +|---|---| +| `LogoWidget` | The Python logo | +| `PoweredByLengthWidget` | "Python Powered", tall | +| `PoweredByWidthWidget` | "Python Powered", wide | + +Being `Frame` subclasses, they support the full widget protocol: + +```python +w = LogoWidget(root, bg="white") +w.pack(side=tk.LEFT, padx=8) +w.grid(row=0, column=1) +w.destroy() +``` + +### Instance attributes + +| Attribute | What | +|---|---| +| `_image` | The `PhotoImage`. Private, but the reference that keeps the image alive | +| `_label` | The `Label` holding it | + +Underscore-prefixed and not part of the supported API. Reassigning `_image` without also updating +`_label` leaves the widget showing the old image or nothing. + +## Compatibility functions + +```python +from python_logo_widgets._compat import logo_widget, length_widget, width_widget + +logo_widget() # opens a window, blocks until closed +``` + +The original API. Each creates its own `Tk()` root, packs the corresponding widget, and calls +`mainloop()` — so they **block** and cannot be embedded. + +Kept for code written against the first release; implemented in terms of the widget classes, so +there is one implementation. New code should use the classes. + +## Entry points + +```bash +python-logo-widgets # console script +python -m python_logo_widgets # module +``` + +Both run the demo in `_demo.py`. + +## Imports + +```python +from python_logo_widgets import LogoWidget, PoweredByLengthWidget, PoweredByWidthWidget +``` + +Importing the package opens no window and loads no image — `PhotoImage` construction happens in +each widget's `__init__`, which requires a live Tk root. Instantiating one before `tk.Tk()` exists +raises. + +## Images + +Resolved with `importlib.resources.files("python_logo_widgets.imgs")`, so they are found however +the package is installed. GIF, because Tkinter reads GIF and PNG only. + +They are PSF trademarks rather than GPL content — see [FAQ](./faq.md) and +[`internal/known-issues.md`](./internal/known-issues.md). diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..08d3857 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,91 @@ +# Python Logo Widgets — Architecture + +Seventy lines of implementation, and two details that make it work. + +``` +python_logo_widgets/ +├── widgets.py three tk.Frame subclasses +├── _compat.py the original function API, wrapping the classes +├── _demo.py the standalone demo +├── __main__.py python -m entry +└── imgs/ logo.gif, length.gif, width.gif +``` + +## The widgets + +All three are the same shape: + +```python +class LogoWidget(tk.Frame): + def __init__(self, parent, bg="black", **kwargs): + super().__init__(parent, **kwargs) + self._image = tk.PhotoImage(file=_load_image("logo.gif")) + self._label = tk.Label(self, image=self._image, bg=bg) + self._label.pack(fill=tk.BOTH, expand=True) +``` + +Subclassing `Frame` rather than exposing a function is what makes them **embeddable** — the +caller places them like any other widget, in any geometry manager, inside any container. + +## Detail one: finding the images + +```python +from importlib.resources import files + +def _load_image(image_name): + return str(files("python_logo_widgets.imgs").joinpath(image_name)) +``` + +Resolved through the package, not by a path relative to the source file or the working directory. +That is why the widgets work identically from a source checkout, a wheel install, and someone +else's application — the three ways a bundled resource usually gets lost. + +`imgs/__init__.py` exists to make the directory an importable package so `files()` can address it. + +One limitation: `str()` on the result assumes the resource has a real filesystem path, which is +true for a normal pip install and not for a zipped package. `importlib.resources.as_file()` is +the supported idiom. See [`internal/known-issues.md`](./internal/known-issues.md). + +## Detail two: keeping the images alive + +```python +self._image = tk.PhotoImage(...) +``` + +Tkinter holds no Python reference to a `PhotoImage`. An image assigned only to a local would be +garbage-collected when `__init__` returns, and the label would render **blank with no error** — +the single most common Tkinter bug, and one that looks like a missing file. + +Binding it to the instance ties the image's lifetime to the widget's, which is exactly right. + +## `_compat.py` + +The original API was three functions that each opened a window: + +```python +def logo_widget(): + root = tk.Tk() + root.title("Python Logo Widget") + LogoWidget(root).pack() + root.mainloop() +``` + +They are kept, implemented in terms of the new classes rather than duplicating them, so old code +keeps working and there is one implementation. Underscore-prefixed to signal they are not the +recommended API. + +## `_demo.py` and `__main__.py` + +The demo window shown by `python-logo-widgets` and `python -m python_logo_widgets`. Separate from +the library so importing the package opens nothing. + +## Why GIF + +Tkinter's `PhotoImage` reads GIF and PNG only. PNG would work; GIF is what is bundled. Anything +else — JPEG, SVG, WebP — needs Pillow, and a widget package that pulled in an imaging library to +show three static badges would not be worth depending on. + +## What is not here + +No scaling, no theming beyond `bg`, no state, no I/O. The package loads three images and draws +them, and its correctness is entirely in the two details above. diff --git a/docs/configuration.md b/docs/configuration.md new file mode 100644 index 0000000..b3a0236 --- /dev/null +++ b/docs/configuration.md @@ -0,0 +1,63 @@ +# Python Logo Widgets — Configuration + +Almost nothing to configure, by design. One argument. + +## `bg` + +```python +LogoWidget(parent, bg="white") +``` + +Sets the background of the image `Label`. Defaults to `"black"`. + +The badges have transparent regions, and Tkinter fills transparency with the label's background — +so `bg` is effectively "what colour shows through the logo". Match it to the window behind, or +the widget appears as a black rectangle on a light background. + +Any Tkinter colour works: a name (`"white"`), a hex string (`"#f0f0f0"`), or a system colour. + +## Everything else goes to `tk.Frame` + +```python +LogoWidget(parent, bg="white", borderwidth=2, relief=tk.RIDGE) +``` + +`**kwargs` are forwarded to `tk.Frame.__init__`, so padding, borders, and relief work as usual. + +Note the distinction: `bg` is applied to the inner **label**, and the remaining arguments to the +outer **frame**. Passing `background=` as a keyword sets the frame's, not the image's. + +## Sizing + +There is no size parameter. Each widget displays its GIF at native resolution, and the label is +packed with `fill=tk.BOTH, expand=True` so the frame follows the image. + +Tkinter's `PhotoImage` can only scale by integer factors, via `subsample` and `zoom`: + +```python +w = LogoWidget(root) +w._image = w._image.subsample(2) # half size +w._label.configure(image=w._image) +``` + +That reaches into private attributes, and half or a third is all you get. Smooth scaling needs +Pillow, which this package deliberately does not depend on. See [Roadmap](./roadmap.md). + +Supplying differently-sized images is the practical answer — but note the trademark position on +modifying the logos in [FAQ](./faq.md). + +## The images + +| File | Widget | +|---|---| +| `imgs/logo.gif` | `LogoWidget` | +| `imgs/length.gif` | `PoweredByLengthWidget` | +| `imgs/width.gif` | `PoweredByWidthWidget` | + +GIF because Tkinter's `PhotoImage` reads GIF and PNG only. They are resolved through +`importlib.resources`, not by path, so there is no directory to configure. + +## No runtime state + +No config file, no environment variable, no cache, and nothing written to disk. The package +reads its own bundled images and draws them. diff --git a/docs/development.md b/docs/development.md new file mode 100644 index 0000000..82c4341 --- /dev/null +++ b/docs/development.md @@ -0,0 +1,73 @@ +# Python Logo Widgets — Development + +## Setup + +```bash +git clone https://github.com/willtheorangeguy/Python-Logo-Widgets +cd Python-Logo-Widgets +pip install -e . +pytest +``` + +No runtime dependencies; `requirements.txt` holds the tooling. + +## Layout + +| File | Responsibility | +|---|---| +| `widgets.py` | The three `Frame` subclasses | +| `_compat.py` | The original function API, wrapping the classes | +| `_demo.py` | The demo window | +| `__main__.py` | `python -m` entry | +| `imgs/` | The three GIFs, plus an `__init__.py` so `importlib.resources` can address them | + +## Tests + +```bash +pytest +pytest tests/test_widgets.py -v +``` + +`test_widgets.py` covers the widget classes; `test_compat.py` the legacy functions. + +Tkinter tests need a display. On a headless Linux runner: + +```bash +xvfb-run -a pytest +``` + +## Conventions + +- **Resources through `importlib.resources`**, never a path relative to `__file__` or the working + directory. It is what makes the package work from a wheel, a checkout, and inside someone + else's application. +- **Bind every `PhotoImage` to the instance.** Tkinter keeps no reference of its own, and a + collected image renders blank with no error. +- **`_compat` wraps the classes**, never duplicates them. One implementation. +- **No runtime dependencies.** Pillow would buy scaling and other formats and is still not worth + being the first dependency of a package that draws three static images. +- **GPL header on every module** — required by the licence. + +## Adding a widget + +Add the GIF to `imgs/`, add a class following the existing three, export it from `__init__.py`, +and add a test. The shape is deliberate; keep it. + +Before adding an image, note the trademark position on the ones already here — see +[`internal/known-issues.md`](./internal/known-issues.md). + +## The `str(files(...))` limitation + +`_load_image` returns `str(files(...).joinpath(name))`, which assumes a real filesystem path. +That holds for pip installs and not for a zipped package. `importlib.resources.as_file()` is the +supported idiom and would need the path used inside a context manager. Same known-issues file. + +## Licence + +GPL v3 for the code. The images are PSF trademarks under separate terms — contributions of code +are GPL; contributions of trademarked artwork are a different question entirely. + +## Recording defects + +Bugs found while working here go in [`internal/known-issues.md`](./internal/known-issues.md) +rather than being fixed in passing, unless fixing them is the job you are on. diff --git a/docs/faq.md b/docs/faq.md new file mode 100644 index 0000000..d4f1877 --- /dev/null +++ b/docs/faq.md @@ -0,0 +1,74 @@ +# Python Logo Widgets — FAQ + +### Can I use the Python logo in my application? + +The PSF's [Trademark Usage Policy](https://www.python.org/psf/trademarks/) governs that, not this +package's licence. Broadly, the "Python Powered" badges exist to indicate that software is built +with Python, and that use is what they are for. Modifying the marks, or using them in ways that +suggest PSF endorsement, is not. + +This package makes the badges convenient to display. It does not — and cannot — grant you rights +to them. + +### The repository is GPL. Does that cover the images? + +No, and that is the problem recorded in +[`internal/known-issues.md`](./internal/known-issues.md). `LICENSE.md` is GPL v3, which grants +recipients the right to modify and redistribute what it covers; the logo and badges are PSF +trademarks that the author is not in a position to license that way. + +The code is GPL. The images are the PSF's, under the PSF's terms. The README now says so. + +### Why is there a privacy policy? + +Boilerplate, and it does not describe this package. `docs/legal/PRIVACY.md` talks about accounts, +personal data, and "the Service"; this is an offline widget library that opens no connection and +stores nothing. + +Recorded in the same file. Read the code — it is seventy lines. + +### My widget shows a black box. + +`bg` defaults to `"black"`, and the badges have transparent regions that take the label's +background colour. Pass `bg` matching your window: + +```python +LogoWidget(root, bg="white") +``` + +### The widget is blank. + +Unlikely with these classes — each binds its `PhotoImage` to `self._image` specifically to +prevent it. If you see it anyway, you have probably reassigned `_image` without updating +`_label`. See [Troubleshooting](./troubleshooting.md). + +### How do I resize a widget? + +There is no size parameter. `PhotoImage` scales only by integer factors (`subsample`, `zoom`), +which means half or a third and nothing between. Smooth scaling needs Pillow, which this package +deliberately does not depend on. + +Supplying your own image is the practical route — subject to the trademark point above. + +### Why GIF and not PNG or SVG? + +Tkinter's `PhotoImage` reads GIF and PNG only. PNG would work equally well; SVG and everything +else needs Pillow or a converter. + +### Can I embed these in a `ttk` layout? + +Yes. They are `tk.Frame` subclasses, and `ttk` containers accept them like any other widget. + +### Do the old functions still work? + +Yes — `logo_widget()`, `length_widget()`, `width_widget()` in `python_logo_widgets._compat`. They +open their own window and block, so they cannot be embedded. New code should use the classes. + +### Does it need internet, or write anything? + +Neither. It reads three files from inside its own package. + +### Why depend on this at all rather than copying the GIFs? + +Because the images resolve correctly however the package is installed, and each widget keeps its +image alive — two things that are easy to get wrong by hand, and that fail silently when you do. diff --git a/docs/images/logo.png b/docs/images/logo.png deleted file mode 100644 index 926ad864600159d137954cf2fcd33e0862f7fd2a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14278 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 F{{U#lO+o+w diff --git a/docs/images/pythonlogo.png b/docs/images/pythonlogo.png deleted file mode 100644 index 8a591b9e6e5ba2fca2c3821dd5809e4425f9c6e2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45544 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

Ta}Fs%2IH`1D6lvyn|I#96TNnGSg&I z>2rCvH^l-@H#GaEiqd6sj=wr!a|bM&5NxZiR?U8qm=AzE20~$_*DkG;Jqyv8UI>4V zj{1PBKK6edwBj#1B3>X1F6ev34P3ptj;9Ry-N5CV6>#sRz+#VSe;YCYGZ8)Qrvsa2 z&Sofd8zoyVBN27IwN^OHVGdMB|L*yAW^nXt9Cl)UdC^V$oAVsP^hlv9-k1gF(F9i6 z-KxNNqH66&nz_H7>oKx0g@aAXg1)fAa-v!5W$@zkd5h3hHCfoEgY{hFe(N?r7Qrz$ z1ZKFV%yVwZN>Uw|#iowIp;lP_Z|!$y*e`8(xIFhUWVdn~25R{hJ4~o2zK1sAGvWfY zqk-*pPQ(=(Mu-r{-mO2LLit!sc`dH|f$Fesj6O#QHblwLQWFaW!!Q6FyPwLeM8=pi zSz0&~3SL)Q4JEWJVeTe;xd{Y7y18V|Jd0DW9M$a znRdzOH$8*EvVg8uQr!yBFA!*^+_Y7AjEqWR+iw*_QK7gAh%QHf%%PP~GHdLI3-ysO zMiQ`Q$vR-fO^c+RZ^An+hny31jYof-5F{aNr_9o)lpG){5(X+S_r&s0AGo|TElIE{ zEpJ9wWzs2ZS=ZF2qg2L7YDoykHL{YW z@Z*fmmrG7!2sC}^d3N(Sbo4Q3bebi!)Txs{M)a7?$ei<*hqjW2F=+k zky8~Li*nFp+tTwOf679nMy?7rf|L~fU%%Hp-_F+V2m7?{?7D{6LF8eO3K0gu_h9Pp zB#CN(3|IK;>i)7l7GMa<2Kn30CzY?@?f3Qod@${c3D{8l>9X(NKX3b6Tfq?(Ze~NP z19Y5>Gd|}#xzC@?W&v9NB*6EO^4y)Dj*GY(*PUeZDKXcwx{j z0@$HDkaB$jQsGdBF};!CwaYq92tbju1H&OeeDDKjA=i-bQozGM$mdk4ZDxF@_UhHf z_0HG6hr6#2@26?czzZb2{}phfcJ)Q#8V~IBsO9ic`wT7R?;I5!D%4+W!?P^d<;1^M zL}dhDsMq!;eW(HN1AP#}oPy{a*iaC6$lH#%u3mt2Bx=B=N5DsjOu^Pvw)*eT!{vDG zCHPL$C^CL>cLVJS2oEO!kC9hj?;(pnPKhUP3`9sYrdRtco@5m>t|~nzaXFvCdWwGQoRhar`@)J* z`ne=Qrp1mb`#wtli*gHQm;(V#hi2d`68&V;a|iAx_=V?cf;y!38VK=5fzj=C<-nKF ztzlmR$UT}$#;x82XwN9SSHWvogQ5apWKO*3xEtn5m#5LHJaT! zXAppA190hH95%trt!$A{5g=B>1h82D$C0o>vA-y$sT+h&Qd7@$R4B*HM%X#Lb0+A0 z&fIoA;=Iwk`j0b)TqqcPg#8s}BeYflx=J;?z2F#SbXaO|nXn9g4~-~lIq4;Xc`eQ6 zssFfjY@C^8bPKpYYYzs=wLE?HnT$XXX9K<`K*NDJcUSXc{&loLAw*`rIL<96a@tPS znxcz`WgsXC?&cul{8Rdwn6}n2*A9;+=zAC0yZTAPn)k>*K6kKD+#K*T;^s;JnOdUt zjw0qwa59z?8AGf@Z*;u4NuUd!z24gAUW~Eav9L(nvMAOCZPJsWGHcV)FRV(m$vWuU zs5>#m+9!-{YugMd;%WA-ZuaisGd+}`GX-w_#V0%D{~N~z zWugGt2toz}L~G^gi*Y$<3q0hGs0 zs=YG?L~iKb2LZMKfJ}qemV*Y6bvlLm`uowLl)~>bF9-qx7y>=L(E>>#>$l=^a&k}} z-MGmO1HxiJu3rG@RAB^EQS~~fnc3#FiEUswGY7mEpap!^)XhBBC+h&%1PHYVA;Q3C zn{kQ%nxV=Pk4WNT2_ys<$v{*UM1+VbXP%6d8#m%o{7l@8SD>d3=~!E%_CNjdl^Puh zx}E_NLlezI12)qCQOB};4uznLTrs(p?N_Xy*uWtVNHYNS;JFrbTLrFR1g(!26niiD zHw>dKQ+ed1vOqJK{I1useq-!AeOLP=E2Uiena)<6tpU@Fr`Is)OuAC18HYw)DQS!eCszQMz(8T0 z3cdPbyya|MRf=plV$5Vj>1%zvyEpQ(ReOJP?C@|UoPAG9TmH5NSB;>z-oHjT#_zzr zxiH6NR@oJB7e%jm==$g!Yx!zHRF>5|NmX@|0fqjmDHP{& zy-w*tJQzHNiIo-qk>Hj8CW)x1sH}BI;QhBH0WcWI8~X*^852o?AZo5UGenyKHKf`G zSS1Fv=5k_a#;i>FkY`2MR>7;Gq8<6@NzLZgrrz2KeS8+$tP3oj)zZ8iCs;G_ZkzYT zKzZ+_<4R$dc@S>QbS;Y%s%K8j;B)z?aoRwXZM3>ZtyWi6K8I;S`%af7SGAVlx=TR< z9dDV$3nHDidRWVPny{`9H^no{oE z)Lw0Fn=8di7f|%a?D@^!@MNDQi@O2qQ{O(n&^V?$0`wt2r4oOfj}Os9MGhN~0r`Un z{I`ydu`&w}0Ea@47R=oXFK+eB`Uq(3;B=BjeM=k$!ovXB-3N9$e3*ra6ZFrasU_lm zq@dykf=m`sZ7Jink&zKVX@P5ACQfZ&L`^K zz}GtrXi&rd4=eLjyf!)*s_2IH6z^RIC?6#la4!lBj6gTok=;0`+P@VKriRq*_J8#c zgdnTQCcay|^J>=KD+{P>5>ukSi`K*2(ixN)y$<|n`GMLUa}mT1t-_0pk zstrjBqo-{2!@IwJd%4NwfAzH2`V4zgo^ieFJ#j*%E?H(sG2AWPj(5Qxxwo-yMtjK^ zMKC3PO+)PZswM+oAkS$LonT>Nx*3_?6CxA^dn4NeXP+5>nR*msK8Sp*Yf=zj?XIwZ z{UM2+F6cut^?&^{y#Tp%o)Vs)-23c^xLGw}DKg&V?TTwY;Xz!iDbmyDi*MQ0jMJ8k zQIBixRk&Zz^vHzEnzn=M-S|E8=l$Dps#!pD1%q6`i3%Y=oiP$rvXV~u;l~cB?@esD9->A`H9zAGU)jrLr3}DjPpOjEU#@6Fp5zQ z$%m%OHq?J;K936052ECJYAf?G$T5hU(m{skl z5Qhy-Vi(V#W(O`He#K^YNW-Rs)PFwz0Y6-x8tEnGA3=bL|h5zUO&VvJfdF`hA)A37iIu$pV9s==><6 zuezk`%^CH&*}x3JsVyFrw`X9q(J}ec+4r!lZ#eZC9M~9;m*nhY(;#OEh7ZS7m8;P{#gpGJ;7iC+@x-YelSq^QfU^x=ru7mLeHo-JX z7*+04*i>}3j94*PC|y(eJ534SKJm3_;$j<6jCjNc_9MPR9&aJ~^AGp)yj8rFM8-xZ zW;^(3`zU=LgZMv$6yp{Y40qrs!|*1PttcI6O?hV=$uz$r`I8%r?)s>S2>>6xP(-=| z`B`>_GmKFaq}HL?Sl}yk0bnUWn|cJwajV?sg*tr~bGixLa4uQ(J|;2Uj`@gqf}>A7 zZ+KlrUYa5xaGxp4ywoNE_huZx66$O|YKx*qAEXVRd1g9q1^I zuqA^=Gd7e!gkt0n#9)85y*leEG{m=+u^DulBNCh9_~=i#0=7(->T0o8{dfIZTsC;Y z03cuL&zLY;_9)@Tw867s^zjC>C1XLi&xX|6f!w_rry^}A*a$hy7;AP?Sv@FR&-2MP zt?1Vi&AELU8f1`FwZv^;niDqvr!{;YkXg-e z(tXi$^7d#6qwAwf8s3VRoZEg&7*(sB@Oh*a-5V3dTK{-}He1D#c^3}bB+1_LHy@e} zoViufxOql1bB~LHD7XV9vq6*OxC@JG4IIfG05qu1P6$N4JTOX)EQi2u)-qOo!o{qZ zgexR)#|zr$+U~ZvEJ1G?N&{cGTthSt5MFEnKLVoE17sN8(K}IGN}`Lz&B_Fqh*-qH z{v?aM>zTiR==dL^49L2krvpqUT=zZg9pDyjaK_ZE7J^-3{cJ5`lg;cJ(|Gp(*jS;) zoJ3-c5m-_{{mUIaH2P0|1P6=DvKrpTmH-jikvGoi%*Ja+#S=%ff%w$_MtrP85E-z` z212{SME5e~&WU2K*v^6flb@9ir?#;#o9`1FxlSCbX32a;Y{3G{ixrQQr}A?%DAC|> z|1>w?UUoV4^F+hZZ{NG(V|+1q&9I++mrgy%%>o-c@?2~1RX+;nEU*$Kg~8y&^EKg{ z;AA(YIIIGCdXG*Wea7GaB(v2YxVQvEYaUZ_n* zIlfWn-Y_L|k;wUrSW=C#0U>@{3b)#Iu?e9A>xOC&HK8y-PtkGYCAuKun$b(gwyz?F zp2!GT=kDJ_Oig{)huvU_1=UXyUNt?zZ1O3gyYQGZenpTn5X*9#H|!BE8ReCV7WrHf z4&M0@!gBj#&x0%O+YQ9beLLsUI`2q$6ZE;h15DaYhzPzd&<>41l0?VRDXL1ecKT*n zK)`u2$PbRTtKUpun6>XZ*3e|Zy&Uv$0Svnnw8`~Q{hOeIu>AvXcu%Vq|7=H><}Ldx z^QTAOb!F|mhRU|9^^Y!#j`caMtztKv&8w`J`2>R{2Os zyM_TsxJ>@5120qCsG{>ibdswhJ3i(_Lr*N$?VIjxN=VMOif}@RE<&MfeUIg|YcF4iy|(=0r{~Tc^XN0R z*Vc?tK{+g+b}-Q$B@LCBdpibOHpn$Yjtfuw$KJ%TUD?=&8wisl93nk`M{<_I_9wg{ zd7Rc@@N`z@yI!|$EsGg;ZemULS`=9+S4@%k_PM*dM}DD40}7yM9(iTHzn>qJ_JIbf6$l`bl)e&43*L*<)!p0XL!o$ zJP9TRkfPaVLKpz(w)KBFwYdftI&it201X{C;a2n6MZ2yU&;zWkEmLZg?*btD&dLx*N! z0PyraA68;yS*`PaqZ8^WRM~;afzLp!PDW2}wm1Xsjs!LroUPUFJ`w*>{eTBU-5)qo z)afGtq58da6LzPM5sU!-Pdcs^z^~Nvq8O{SF*HX!=S6`MZ8@QKS@uVc_%fk`d;jycv}#PA?LM zy31uSxv&Z4yIBUS_uc2y;t zs05_HYjYoN|mM5kLZIZUj<}G@H|15mmK`v(X2JVHI!_?RGL!1!JhS)EkqI^ zdHy$a1iBGf{0xhpYw>yxu>Hx#D^9iDzQUO?GV(q?BL3?{{)ph_3srQzeSIKl9}Wzi z3Z=dOMo!Wlh{K?1D}cxi37w!H1vPnr{0OjYP?Zh-IjH6#07|x+Z%*IdUy=L-z}Yk9 zvybOco?l$V8asQplj&jM=7tY3+f!0Hrc3mo;;^w%2xKKk@O(4ggJ0Y1NA@Z(9<%}W zin+J9a2mUIx+oZJ2r9hQcklDatd3S7s1QV2XZ&KI-hZ%ATe9twbelE~XgdIe1jJX% z&E9Be*MerpfFbdayaX*Cm|YcFZeiUb{vbepNW8{P;@;t7E=W*X(eblP;22^VJnW< z!BA$Ujx36Nq6KSraU??)FVl7r5!RxOU4)rc8bhr=j4r}oH{~x&#)T!)3jlT>P9Nzd;?UA{VjoZEQhrUIS z-G;bN78Xc=>zSAw_NC2}Amb6iX;* z1A}ovvIH!E>@q$*9lE^@9i9`0Uax zKohm~<+O`1RY&T(2bEm4C^b1=4)>*tVLaDZvp=`26pv;Vtt{4E>mLe6!`aw!S^d`dS!Q(uBfhA3 zzccyx2w=9MTuR*@mRt*(A+tzn%Mbfh>!f_rQw`ZP!)2Wuwo(1ph3duhctohfzlPF% zX74yvS^@GD`*Q(H!W&_d8LYu{;ZWwXFOKvCEQ$&2((%YnHY;W{=s#((Rd#1@|9oyZ zw56V=G@aE>chhOpE!H>;dJl$&{Wq+-mgsaaDYRyzDRM2wL#P%&5{~LvU(s)89#uCb-4i+h?VrP-ZDh@N-zll6UUCHfVJ zX)E{r0G%&EC+f%N<&0%2$2)z6W2(#xf0(_KCmw;r;mcxBI`lUJ^G z*kr@usS&{^8^_&u7@_C8#QHR>MnCZ`l(A93Ie40@8Vu5!fX6x7R6+?9F0ghQgfx2n zyHafrwOQPvv9XA-Ta*$}Y90S-GalyK?sen9{B$&vTi@87Fsjh}A|#dHMQ>Gax_Khn zfpNYg#5V6h%V0};|7jNkA-gBQ;G>>Jex;5>_yx`H3e#3h1PytED92?d5u1gW4Db?x zifK_6r?P01KrmGhWuG8QdfBTdH}5#FV3}XUxDliu&o&63SY+it*~0uXHAsN{sA-Bp zOBjQ2Si2CTHkq__aWMdPEgd+TEQ0m=VQ6@RNZm#Op?T$vj1dU2hWSZRj z(7W;R&uzBa`foQf-wW*kbg`n6P6 zRs2%d`mWXmi$r!mu1}d^sWvUuiWQ~juW1l9P_#9ex@fs+C5l#m;x@f!7v0?SNLuNR zY@i|Bn^c%8{G6=$|4RGrpr)d4-GtClx(I?aMMR_{CDKGdiXei74pOC~AYG~msEDW_ zN>`ec(3_Az00jXl(gFksMT!Iny_dVAznORMoq7Mfm&r^fCpjlOd#}CEUTb~p`?@z8 zam6TAY7ou@iH*1MKyV%S`~wt26Q9r2ZWrE)FmvXNjUVJxmT*K7d^w6#f80z8Wkp@w zb;Mz-t^DW=_wK&b*b_bSQ4Kpqz{w3?waU^$RJ{o@ZWQ&dE z)XfFQm7z7IKE*5XDr}rDqlrG{lQ8ZI8|8u39W%u*!BREOKd-4gCW~LBh-##>IHZGc zRt~mmOfN@<*REa2(vadSFf%*>5m>N)XxczgbZUc)Ehs_(fuH0|roSDs$ZUQ$x1cLB zkr|O?KWxG;yoA61*4oZzVZKm7ZT7M|v#^xb7hjH2L`p{_PQ~1_uZGOBk+>iD{i20p!OU_MQl6-94FkZH2s8vD|xYMKp4(4|Ia>rNxeB^+2js&bJ z7~%v|-1eD0$7yJpno!i@NZuJ$?#m^&vuquB+#{~u+q2I!lWr*A%sO(r*E8{p$y;7g^b%5ZI?HIgvX^+w#aj_}^?d`*qZoOIsPFDJJ!c2F{cpYIRtHS2 zSAORt0LCQX>eLd7>zy#b1VNAc_{0ofu4ld!es8dMteo}h`^39JIm$hm&yH;4Xxl`r z<3xC9QlvX|nkV%5vj=>B-{f(s<#YA)hb9-yEdB0*08ptCc{oq zOQv}*=IHxF3ye<{`n%2okx5ldcJ&nl4;)VX#xwsQ++Hev(Q4lj&H>w}W4N1Jp@gU0hGJYQEYC@gG<5x_+La zlNvPU4v0|#<-OIPQaz*;7(~A+HQRu;foKOXtt9H>?Uiwzr?(i%%SI(%MTMC#zK4u? zV3x`4xm65gpBv=z>mnf*rVgCArYhAR!rs)QS7c?9=jB@Ab}p^nZMy^GFNhVNb~*&1 zLcBqg9|F#5E}J~z{LU5616h9>hC3y0ccxsc{4*rG`VXz_w=Ev+*l-E9=YESzW}yHw zHU-4y{g1Y=YhZ{z12w^S?LRkKadTE*E$CBZ+?(BN#-o59`!5Jsor)w`-w3khP3dK> zSz$8z+q18z-4oL2Fc|mAOt^SOfN}JaHuIO+OllLM^*HTMo((OdVxR~mLlrvKhSG+| z{#lf)XbWF^sv@pryz-2wcZ{u`I$?M@i>EUc1`aiH&tTl^7 z{t>T}@^3&zVr|(oloJq~1AlSj^O|=4@qVNs_Z-n%QgQaXF^%V z9>oXH>re2q^&b@0w=kqs>d6sthJ+IV{OZ6tYho{~3yow1c};!osUdUE?;t%90|eFk zc>gW-i!AgP{U9QZyXyP8?nw zD%I{QtUPb|)hh0&NEH5(n@k3VeV};2|G7mFB)V`^E zp3QCSYy7HurZW#|$H*RaKQ`Q(UP#~xK04toyuMfhm?4mYR6d+ykN_mvYip1GiJ%y5 zeZvKR?3sr`fUo@x+pv8NIA;BZY=1XDYL@TD$SOnG*x{5hMQbI3kQEoE5|dZ0dYC5+ zfQ2YQpjy%rDk!a0Rc;$F_`a)l`&XMF-3#ZJv2Rr#aedeoif=3mKK?n_Ij5B=o}IOJ zT)VQ~VL5(VdpGRIpPlXFOT8%Lp!w&76iP3vOPiOQeB9#=K(>{X?4x1W(|Zo;0HC31x+FBIG!9$Sf#B%I-B)X<3vo-J_s+;F+T>C9||^l5z~qjNbb zLgd<*;fftAS4Fh{-^)o=2e_6UooGE(e9%o$f*tO_djiwP$1NitZk|wjbt8=rrFDl# zMo0|*;SbUSC;@xuG^dK%H{Lt4IYGya!$(}Joyt@pTVfdhq`_<*oFM+Kn^d2d$c3YF}orhcx zTl$%z2c_GlHGf0Yj~r#+i5%jyI|(4~7p6U4>2a+7|CWIDegi z&+-uV!}3lOQcV0?X!GJlY(7d*NMNWl^frk;f9;4E$^$~Kkg)2}mDHQ~otR(UW;dzb zXOC(j*2Y_|99@9Ve~rYGOUj&+U}hxAP4^vLHMLXgkEJ&9!pFr%Gp;j`5z!FTNe{x~ zf*=GB8%>lU+7_-zbWbT_tyaswIE(R}e3?w^SD-+6I|pzqt(#rQ@Das2b9$Z?qz$;5 zBR8=)x#0kz9}a-X9i6#Pd>MZ|J*sHMG3Mlhfi`;-6a>B8Kb04gd!j11sJGrM6Nz?c zs~HgPb9IpH9NZ3^&Mt^XOuCNTHiA8IXV?b<6f>Y0f)x4y;eZ>}Nf${SYA*IO1LCXf zXtO-@Rlvslwmt2xGTyIpGwy zyTv@pkahhir8M$wp6XXcL9bzcCv2q~5H8rEAW6>muihU3C7}Q%^M_oT!a-U~Y?ar! zsNL70u|28sPmhj*BN@%wKIYT~HY_O^J`IXx63W@0AaSXaAg&}#11XpK8YIp2(iPfa zx+I&eK^av@Mjnw`g421IZ!nvlOSS2NthFX)I{U#5p&6y5Qjrw=;iYcSE)qHo zxEmVX94+FNgSHsN3de$SYol+T9w}-?0{3PXaJH2nqxEc&Ik&4`>YqLd#?O#81&jH4 zt2tu9&kKovEdgg{30c`YKRMOQPj$_g12Ji(dXkI>8)j1B+2pIv zshl&Hiz+Fzo^47eyo<0TsAbVEga_w9W2i94o{+po=-5#T=9pzR1g7JpBoGu7L`rO| z{m9`mDzZ;r5?|j`?6MNdl)5r(h)T$l<~* z<>osf>ntb`xn_?F=d@Oi0MuaF`?}N0Jr>ta^_?s>im< z%+7CzTrah>WGk=>rbYTEmEVyNKiS@KMeFJYp5b6tc044v#$DU3f$ZCk$Wj}_)mVlT z`ftK1*EW?#q7d>ln|?44_fL(=r#JoHZzrAaO`{w-8#Xu}cFZ;D_wY-b;!%cK3D%?p zOVSF3m}@nFPF(x_?hb#e|8EVGx-#Aq(wab$G&?@#-VdQ*GB;HQvc{muj0C_>h5OKg z5tIww7nPe2D0&{l{`gL zzJ{Tl?xgWO*4LfOt2~*E!yL0S$AlS0l5hz(HUDQEW0FS<=>Zz@_w`2l0(Ak0kUIE~ zAFL9B``NRur}po5>7#uMo0gf@A)_js^$bV7EsqM`3v&{#X$qh-f__pKCw*l^LZUZ8 z?Wn8$v$_NucE+s4`WWi{L6l|_R#sWOspn+L6Ot@dkJ5HYh#X$Y( zmUda<=r_6di4VgWpz;E-En!738fv&lwj>s3_8H?1n&sja>geS)Zp+`)QL#oMmRTYg zRXMG#i9JeuG1Q;Lrj+>$KNH|Vdi~^sr{)z=3~g2#|Nd}BUFrph-_k0(k@^cJC2~!g z$qAgA=HS?+n?nSX_Rc4Yg0{k&vw>i;{z(%Ovh85!@4YS}yf7M75{OTH=y_vIKH8Z} zLf0^8td3b(mqj%oF1g~FSCyCwqiWa=w}eKvx{xmV=L!$wBlb>Ol=p1pO{pjH8ni+s z;~gPt> z5$)}(%I6|@s$ZHfkKEeoW#Z<=FWpr~LbC|J3q+ z*+FLKP;SfVnxr!iFrPL0E*JMhzU4XQ`oYJI39^UUy+ytET>91Hz0-|5Ivol|wO#d_ zYl4{}7mapL?RF#n>m$K$jTaX$jC zhGRbw_FqY-SJ);~LN2EmQOwBMqOEX_#zvYnD?$&7umnUsJ><_Mq=1&FW2$#$+&&6= z_xxL0wXpLg>~B>vS6@Ecx9^<0)xd48n^7Wrs`@Sdd3TM-=PU8hF1r9F?qI;J=2^8? zl}ZIc1Y09U?c_N)dbfmsC&cH{d?NlTL41g6a+%XP9}){wT`)g=bT{eWj5VZN;4enj z8efZqpN;RUT=N#@GqrNWzI>$GO-qDQ^Xf6GKCraycp=T|f3g_aJtA9x&}NBfk?y)S zFW)1=@2$kuinf=d=2htqOY)k>G7TnTN}^YYfi9MfbFnt;@fFSTDjQ?D23+y$j^^5z zOoZV)<=u-9n8s?A%I!T64tYS|GmHNgskZ&kCPdy&G4u%ye9e;{{uGT6z+ z;9FvyJ6&(56;WPLB`2XQVLd5TC#@DU*mS#~+KXZMg`YXaS@RrYDlxZI4RM$5+gMbLQjWW2kk_6YlL}*QPRn%v zQS}aJWH#u{-<0=#RCtU&9NX&?5Uk$O`o^bch`WahFkqWXbvd%$S!fc?HvW{^7C?ig1g zFYHBwYj6vx>P=>Y`g)rTZ1=e4r6n*w2|jAGxWiVpwxvW^_U_haqRw7ERl31Ku}B-b z*Fux2H+LcTWs9-PEMW~vRPWADJJt32BO5U(*vp_Z)did3@DOX}cjxb_5-Lo&XEDlC z_g1tj@hvWDu1NwLd(UmUXvfyY`lWr*-#?IHa` z`X4R=@GTR!l6WzlO$rs!L1lUay~x~GECs3kwk&0pUMa=qiR+x4acA}$2Ii9{4jo`u z2@9n4=EgBw4Vu}LPqF%R;YMcGJ$S=#lnw!udfCATVk$iri>Ah4CPBELEmSv#Jbn{-uS;H&IK7RVlsxw^LNN8L7E z*jg^v&#k3z>23B`yt{i@kYXZe7x~HL7~Ycl#My>Jd+*hihvGDWd8=DDncTSR`>t0g ztW=t~mvGwVNjec$vrRl+2#{8gJ@b2MPK%wix}^tkKEuFTIr=RP&OPZ`iHl=q}}EGW@6!VzL5-kW*XJTgT- zYeZbGL6gN2 zTzRQf)Nx}6D!`~}WUE_h&qOH5nDdCXlp|Yl-M0%rVGW{}J3G)%3$Au}XIo%vY;INQ z+(wF;N_&p@({~bV*N)0Ne<}!U?^>g0U7jckm4>Bs{2uJ;DzBOg$)f9y-o2O^wYPs* z?P(pYIf#{a962mi4Vy%wG+oN^aG}z7uPcWiU&jyW!4IcDxHTl*s$wDa&-9B!C~`H2kdgc%3LB)P1)f^{4*^`G?&6!Bnw>u9lJef{(fzyjnYi=-(>7PYQ5Qa@%@T zl5@@H8M^vi5fnu^xQxBq;&%E#Cd~)FnXFD8jIYruOOQEw{{Qry5HG+yqd?2PtYm5w5Cnb8%I6rg|?22}am-=-U@{L;!u< zR=1W9b;u^2&R585`q;$HeUnb3t(mK`72H*U)-AsH9pr!`SDT$|y$8OUP`9lB>WA01 z=BYRq)F!`cs4P>u(&Td>yb|1D54Das`IKAXteqFg=@$B>-*c~VPna8j%F0ETU;1b0 zo{#v8Bh^OgxK<}30;o57EKJee4tCC1A25xODLPeVNO4^jl>NXo^CJwqyHj7sh>MR| zLg_&Kl6t&O=#GQfj@fl0y3ykUo_-m-|J9q`5_|sSr4?e-RY=dW$+|jgEEjUgXF>Z< zYyyq`wQrqwuW6_ps9kI=tK2R^@42ftRA=4m%HeKkTyeelufqhMqPUo*MQ)FVeg0}s zQBb|OqL>{ydTufaJyc&@Q5{=AJ<%dB3=4-eRDOC~3f1rX^Z9eNA*>8wKGe{b zrX~w~TtJ`mhaQ?D5rH|alCOsXg_VT%>5EPBRA->y_!5NOJi0C2OhgQgujRd}+jkH- z@`Ae^1s&~`Z(FKm=Bx<#M}G->*R^t;KO);Vg5RJ{qvO!b$h{7ErN}X)bA4@&C4qdt zw;8nq?UznqdEGm4fo|i4>kf=$|G>C%OiQbD-&J*w=EikDO{lDlFDjg=s#fs#3|Dwy zZ}gZCQXnJkGE%SZ@+Yp+>=9GASo`?RPdVW)Z#rw`vsJ%?+YcA`ijMfycV+Ex-~C=} z+!2A=;l$FtWMRfc$$V#LQXL+a#<^?_rdOU-HweEOFuf%gbKf95hTm=0S(vXJTiWlw zLifeed9f7{q-RMpXQo$_J&3_=dE*w$f(|?xwm~yV?d)>%OeTN$B}75b&^*m^+@|#x zSt)gt&4>D*k)=$Td5gq{!uSB! zYdHASmKMLc7xRz zSL#x@1SV3o@qO>N%X6&Qu0cN!x4+A4KwX)v5_zWE@$DRR)`mB6w@#Iqdh-QSK$*l~ z;;XD=_kmBIsT7+!y*0b8 zd4rm}n=0G+TRcQ;h+C?#8JoPTt{96cuVjIaaphBN+v7@e<*Ipx5b1oInnLfl(;^b+ ztr0B^Rqr3aJl)RO6Gqxn+(=jAGOc`EG&No|F;`7fT|E8L+x%UNq?$rDp!*cUy+H38 zNZJ}Y3iQ0QpkON|P+B-u2OjJ{v7h)dn#l6h0sZy#^D92TXQ$0Nt>EaJ@l#x->rg%N z&tKD=e#4Eb-$N3;Qi`1Im|cTHa;EXo@aNY|b%RHWXa{s_CiJw&6cp%66OX$v9wL(H z`BO4~M=$RVf3KM8@>`F}1oCgV0YGUPmrc5-9 zH%IEUSyFN;(y=W%OkwuB<~?)WvmeC_y7Y$~Er^QJIBy!h`yDj;LW#-<#0A@H%JPI( z$ANQWggFZ)yzllqlP=7Q!BS}5uL7qhQXI1Q(Hz(|^+cTv^ zL|mDB$3W^EJGF%fOF@Cof-AjlmZqu;V6TYec9;6%W>KA>b2iOvu43sXJ~tO0E{EAO zOAyO>oO7#Nuk1-R_&Ir(Ke-j}E)LrUj-25`vBQQ9+T#HFr4FI<~mp z3moCbUFb8!zsi&)f@Und!<-4IE1q2}cb}}hzl@5OD{H#-33plSV=L1qqPh9^;uOK+ zTvnYwah5W=b^%m{yKxFa?xRXCyY}KH92=0Q-<(&G9p#faizoy3W91e6JII!7FXVeu2QvtgC5A22 zi&W{_#TuH@WaRY?9pqd3RFZEEx>Wg}dd+BYFp=Q*!on}#LBfI z(TILjIkYIoW3Ig%GVV{e8$h4$gIOg20>%T9lW!$gzlO0H3({Q82Uqp8B7c|8>Ft|D*r8;QzYr|2(=N#r)fP#)g+Po^|=CIkn%>3iP1c)YN1X zdEgMSbvZ_oKQ?~P>T$uoAvYE2d!JJ}?u-*a#LE(bpDFuys?ZZ6NS2*=ESqh(b2I$= zR&xzhWzo<2U=$m&Q)qp(n6X~__hP}0M-!lq{^SAYjfP!#SmV?hAL)esp8=E@{E%n$ zQw2~Y;MW{<(gsPNDI~n5C}xzvAW4) zdz;4&a62yt@B)zpN~9tZ;v(X5_r#^);u3IiIbm^exVZS`t7?`1;{ITOeQAOU{{P5KMokd~#hVrdb!x#lc@FNNeiBo#B zsxbHh%~W1m0_EoRPgZMTJPL~IsH}vzhUdigl~;nns@JNQ|E!PWR?}|Ei#y*Gw(h+^ znIeg;eqoc$+>@i3G+~=K&V|^vZs-%`S=`u3fx!-(sTyKRCs?%;?fT3=KkuVe>>Dwa zC6o*k!h}A0VJiKk%KQmI(=M6wuHWq0BI|=#A>IclnMeT!tds|QPaM!V15UaQMPp1c zC+qDmBF%M$-imzj`$8Uc|0Txbp!*T)sD|ixHf6IS9$RC4#GhkRZ!pci>&+qG#(WbX z{PUBA5?}mNZMotI`4C65?`$Xm46Aatr@nl@xj>Sr7Et%dm%{A$Kd}#oPybx>tNYPM zwT&izaCGCXi2&Q5i@cn=eQS<4vUI(?AyCwJa%9<`)(-DP$#Vv{O?CeYBn)ukxh^1FZ%grmp;#4u}Uka=at$% zZ95XXLK_~|bQ$^c)2|nC92PNmYYi*zdczRkzG2Lsk2LUK{&>9AtTeJSfe6kO>pl?? zSo}NBt53sCFlh=>(z!F5Hkmg4;OT1Yik$eK6k&(QF&t7#4S(+LX;f1_`tJPVLg4fV z$BYP{ROg7a)mU>3rVlPjC}eP*8@8HVm&C>TXXwv-jj+vdDq0S(kgb=*X`-jkSFl7Y z;Lab_>6CKas3+^e0(T$g{g(I>(3Sv5ay7xII~f_7g_YHZ^J5Kg}e! zT`n^F_7d5OFcCL$uD&)4$%-s}ULJ2X+F5;^5o7CGYnMB8#Kj7Y}+#e(6p z8(iv-+mIFggVpmGN900K?#^#|v)nH-e3sHDD*F1@XXT%v`W{<8adaoG=*s7`-W9iD z5|b^(P0=R*<;a_PF}3Qsl46;JJEyvLJ+&%&Lg1w|s^O7SXJKa-d37;s>{)ArTwE547HvJMHp6o3zJ=0~}T=dM9;vLqV;%Vfy!&?W~`GNnMcRJmP zBqkfZ*tpo8h{U&%)V`^OP&Tw?Ihv=85HD!+U3r>CIpz~jY$G##q~DpYXN!&?R~t_5 zrDr~p#d{~Fvj#b+Sk+>-evy#AS>#r*LruM_x3gh-7vg@gE-KUua|-kMZO8W%@@AhO zd9am2ee52j>~9wo+st}AOiZ)-0&@kp$Py%aa7bZp^sr zY5mQg4SK>8y4%zw0P{Q69hp9|j^nZQyvW~;`(*WkA)=#;q~}KlZN`k(G|bLkk%fu} z;$$4DiXo3GB`_)Saufm*6hVFL_Ji#?Mw030Ouy)6I@nSVy{E{V54iL8(6?HBi^~3@ z%qbXmHj^`%@L%^)Ey@{o%EgQh2<-A4r)N`SJ^Kpo*(`D8)Da}6|I+8 zJ^|}U=W3qs(HWMr@af9~w(AZau^!ke%=AWvB<2l@+u+gGJ5${KHQi?E=0@9K$-ZWv zH!)4a&X(UC?* ze15nMxg$j)J*5Au59OM6|Fw;}uxj-1km!6 zahZsfd5k8bW{wo%W1C(7+h?RR#bM3cx7cyahT6xyL3h~e0RXs{yM^H<2y8!<&Py-Lyj~wA=5Hvu~*9b%U8}DEagsv;+CT|lo)*! zIfEgI)f)Ewm+vV@=wdRm)AR&wNv7WEH3v@qDtC&UVDiKjLGEvb$B-mA-HZ4plD@u^ z<7$L!c^vwm#}>}CJ7fztDR$i=Xr~bV{n{&ZOK;<-!Yy-vLyE*Jn#bLpz52WC&RSlC zWuTLMk855*-i}YCYEqMqUcXtz3U8_KpFR>~?JOVc*jK$~BlA<8in^CA3mtE7uaIUX zT4<+nV=>7COZVe`v*+;_U8$4%N$FGReINT;Lx@<3pbw+DM7B!F%xcS{Q}=QfzmrBr zN2!h0H9R|Hn=Np3?wcyKd_5l7s&GzQ^pVUwVIXcWZeep=f3#l)Lc$|YWokzhBT_%H z`i5uqwl3~ByMGv^vQ#A9cP#C(oWeR*7--%t2 zJ61z{PF=0+7)3})X*sV6N;S_elcr&=T zxJ(}6P1c=!FS1qUiY;OD`Pzo&I|rBr$2XSn-@(XglgX z;*b?_wUw#8I8(JNOTF6HZp$h#10#ZUx}2D>qcaX(ZCLQq-7}26Lj=}*;p%=13HF>=*u#YGZmD0d@I_u5 zdavh~3clqCSzot~rWEL)xf-BxULSmZ4LV?Yo$crX|Bon0zMEs|SO@ZN>f z(0~1df3DGHC%%}kJq2r`nudmk(`v?>YX2*5T3T8MrzY9g34!R%tM-C~yN65tHPaAb zxbn{t|-&$&;LsFwx{%n6CQgz~dy79){aR z0^fH0WjyyE!v7Jk|9$wd$8vk} zKHhe7asz8SjcEHo@Yn&n?Xs`!d)pb`jTFG(g;WUKm&{DzK0GZo)ympBw&qDtqeYW} zk`lDBYzBF7p^D)wBH)4*bf52~pPxwEd1;#*V`5zVV+V#aUzpg{keIorr;bv{pOG(& zV9vH33bnm5H_uPUah6X>PhU#0gvElPH$Hydng4f=|KE)Mzo|X*?E~?6ub(zTZWfsi z=KSXu3sUI2fDd5>L(_3Un?#k#1d(X$`u_d9)A?^}JQ~sOO|GjSVX&3efa}%qdi%6= z%Kx3|E%;`K@|F@_oa|b9dXmnbfT1N20P@^`!XWej+)BaGk*!cE!_?Rq1>yYdHRo78 z3!N0k<3Ay7oQdmsR;+q%u<{Av zyYj8z$1p@-2)`BRIf`*&LmRYR#7k`iGTr&5yLF<7f6$@KF>3h)HO9F zdDEhVKJx$QwS6)W-e5o3Sk9EY9DIL)_z4rZRvvni7~+9(bEdY@3Qih1A7?9kf$@0e^B&c(r%_KygBn&D4}7;z7R*{d zQXK+eu@uK}?&Ij5yAaj0jpW#uwk~R&NHj+tE;MgQJaLvhVZr^1R!M?63|sB`PY`P; zdhvtIvr1+rf5m~(oEVw)QEgXPPJhZkQ`5-s!P>`xv&?|4BEl8#gw9hqjo8iLO;Xa< zw;<)mU(0fuo5?L59F%^5%ueFsf`pBegF`%9C9AwVIwS;*k&$r$@t#&+ih?zHGEYE6r2oqo zl-AbPXAd!X?bfp3*{~%dLyd&q)x+OMN6s6+7+4J&Ul&-0ks(NRPM8~hsx92q6$S7*u{_{9#BKTPbj9iQKQLxb`|+iCtyv?2vx zT%Y+O`{i(jf1<<_anVdm5Q^8FVXIy^xVZbBG}j+SjRG=KQpgGl3&%gdVT%zyz|e1S zU=bo2*r>3d1oz_ijE;_WS^N1Ik4o_C*RS`=H`V9~LH*LED8%(Ie=~P=b9X-&GmBA$ zKw39`3WCK1wJ_cmAa=W$%F0}#qCbB9BD{?(rGQINcsQ1gt?fA6Pl)E`6j8Bu+5h8* z%fXWDjQ@o_2=JG^J$3+CFSEaV|E}O`60blj;B(9jlmdX`-@G&NQA_2t1TlyAC#x|5QU z`l%P+Z*iMzVG>ZFc2v~WYu3ynV`5xyXGkslUM+lNWTY{DLC&Dj>D?kC#%z*z+%BoO z2h(>pqHV{EdKH<8{wPtdE1#g7)L_)y$?3zpcmG*fTBf9=m~2nfF(0ud?_+NUqm>Q|8zp}Mul4A%74Q=v0^L?!2}Bcj^g0sgIbdU5K5;E=&eVRG>u=v_GCk! z5&7SK)kyyI=~GG}k4O?j&v)8Jene(C!^6XFZf+m?mWwJX3gK{AK>;l&oR1k9%X{;k z2F-3^^YbPkbp-s*xo1zi`J5<2A)h^}#tf5-VEpktSqXaX$Zb?H4XRKLM#(3!k1~|l zilmkD)u!Ie`qAfqOizDpZ2Y#TN49oELtDGXqMzKx#s*xx%NzXJ?U1OV2ESq-R%D#DH4Z zX+1FnKb6f_!-iggln39;3(cP4?ZPiu0iF2u>sO`Ei38}{xBSB1-X5eG2N%~X01ngB z)9FHQq6Y?4BRK$)?QPW{O(V05i^Blmob^5Z+aa}WZmzF<57TCsF3%31#miD6Om=5l zg^$O~wkGOq2QGXs7im_%yu0fQoP?F_hFP?%!otviOGJPKLl+=MEo)afxJjcEl3(k$ zp9lJAY7(_wO}62F>0@jA{-*5$0(jD%aLoC+_wn{5A`oA+acf_mPk`L)w&z~V-iVfO z#`P_a)mjtW(t`dZ7X6}6pYDBehbX~>d$ilmHJd+w22M(2dEXoOA(h9@l&rq~WX=%J z#rgSZTH6`L@$PJlxo(~s!^Gs|S)$Py5wGJ+ixmTM6n@NeOJ{%)0B&F5yUe7Zq;zn) z7*pdg-CRAXq^w*MaN~cy7IRGxn;IV(>CTN2?FDSM%N*Hxh!jH(DU01A@VZ-SQ&ZFF z%Wc=pi}cIo2Y-6)dnO)!ewl!P0E6niY<$1>_`Y*@-8?*4ecFJy2?Wu$u&`L$*`ZDD zb6)vQ24K@+3ttlv_R6jn3fEAq+r1#f3igyU|7E^xlQ(32yS&tXzg2l1rew^`&2`y5 zC_|$t_zt+l4!L|!KF=a$7{rwO$>M5_)40D7V=n!-F9b1oxqZdJo#25K} zKlA)o;o91oPIcr`eC8z}AK|;ct3m)x0LFOjcaaoVR2bcdudb|sOqXDgq>ay3p|7+= zQj4DTD3_n6<_3tLc8XoT0(2mHksSbKR|Ls2TlD>fg6I03!T0%ikcUnXzUvzh69d+U zEMJo<_GXZHw@}|$m$`e9F6bWqR63fu(eKyJuAcr#V!50&(yO@sEqpiGZ~CyM)X@Fr zE1hV&rPzfoFfql=%$}~hH8cN~Cb^Tw=U9-N8)(N%QStlafKyJ~4^N#e%>=+C@9#$&C=6B<^N9+Y<4lZ(yS+3(ypM`C+k z13*@wU0+`hlUH5&Oid6VpK0_9+oyOj>3BBUaC3N~-dqmgCBdNFf(4WRv;W>Zz=fp%WD1k-dw{i?W(gixx9N}J& zSsH-mprJK3G_HEdU_<@^AKv_h%^jCoL7T{SXG(y!0)U9ZR#`AQ`cRjdyx`gtITgR* z+7|}7KiFZbCc4C+w*f+%Fl_O>xLGAt?z}ZA0|m@K_xgIV8LH99Ngid}rUn>e-||A-!@g>I zLM)JXY-A%Vj;SpV^GinuLb~&{%qxzaa~35jcq=qCHXcBH$Ld?>1n}_iI0Xd4%ypgd z555vb=P83Qg5_sA8VE)PW3Mi*w(9J)JsfC5kx&-{YV1~;8K4h@G&3d2Jo~onVpUef zj6GS;K!^qU9~%X{g7;g0+pY^DrEUH|?#^nR!K3eOyQXz3i;Ii<^l$PBn+$fswc+-Y z(V@hWB)H|9ob2qCujithlML3oz7E610A;14hBr9c#nn6tYP6OV=fFa0H!}>>Z#S|S z5^e!b;No%+QjuV2ySuX-O@TUG${@mkdnKO{I7qZ!gt}N4GP!nr<}2zywRTZG75v2p z`sVix&>v}{z9%c@_bPxSB|MH|3Zb9;0Qa$W+T`8dT`P}mMnZE)mKzGTjfKlBVgSR z;0QL##M@Cf1*in4ZR8B>YCo(7FlT0FW)6`720h3GK1gUJ(|Q7@Sgm2$px%DI&0uLs z$v2A{=f(^e48DMHg(QcCg;norGbZNL)$!oX9`a>e=kb2V0;=U$NKxtC{RImxz3cn- zsV#9to4%sRZ{K9b_dybYOp!;MW`aPBHsDP5jRsqF3x{J!Rb_6g|qk-Sw00%!mKVR6* z;6R(KFD|W!$h^2zEF7(l)%YtWzq)e7-f}eNmxQMG&Q9FVn`X1sP_B#n3J2^O>*`6SF!rO8Bi5~ zH_1GY-?z^IHQoVBHO@ka& zCbzeXd;9n-iXr>^tK2uWs6FT2p*EC#`jl5w!)3UBZAChG1rko}~jq&mZ9x2k}XQ_aJ< z(teT`G~$6xe^p{gkW3S>!2VQkE)XO?CtY?<4D>A^ z%ziD_E?@%$v>VOfRjb5H8#$JhQC+rSaf|*`9=pkU7Jo|Q;TRAvvu8ivX!%Bh?z)#t zb43qRXg29YYi@2XDk;(XeerqFRd>D4pwIZ(m>^_&kT zS=-$$tg4EQj>ani74(`@CrMH?v#_l#a|pPUXUoY=PV;vFlW1n0Y;d%^INts>GQ#Sa zu0Z?B=R!|VkoV{4Xz1=mWK`5aM@)c(yXJE$DyrJLvh0F-G&<&pTk8B*d))4~xvkv? zHT>*h7(b2_l^!uj!|&%un_gfL?A`1@*@6-AgO0X2T48jYE@93M-!*ccKDpd$)p(0s zcCnkN4MR}-MBXaF;$jAGZ|~E2`~Vq6MO?rVSSf^Pj_!*6lcCbllUPWohw{n%l1uQkL_02{!Vo;81ZTH38%yIp{Mz}Kazy@GgbM}X7{TzvL1J#{Ig zGt>)+95O1Zs8=>VK0=wNU+EebqlJk5aQf6VG_@)nXGO2iGH+6@udmtP#_ZpEpj$Jo zX+m#yEvB2@^WtPtSRu_{ZwZLY5(e-DKy`s$1iT;MRVe1j2TuZ-0%)m%x;jB_ZmuT` z0i;n8FjL#nX};Fm0|5$3>j{~tg|%libfeCWJCZktRg)aF)E{iu3v9Q#?6!o~*61yf zuw`4L3v!z4y-;gMN4n&`?1T>M3e!{}gh$~V7}KlNPq7bJgViXmsOw`T$GKi#qv>jTWY`BCFJJZ7`m zoJy~pHm|u{K3henzRZ+0d66&RkngNU?1Jl-%!8ZWQlXo5u`9Yr4ri+C(^F619T8-1 zU0ouZ|9*t<-j}*d+l%ca)$9sy&`y7Sgx``XW3G92CPur*c{2y`L9 zAOurIONTsLD`AXC43zR7gbV1@u~r{^nzJ=TQAKH&p*de9(*L+-%6$|<$?x=*=5h{w zKcV}KsT7c4Kp3lT`ET&C{$>BK0!JNBtGP#bQ7uN3X6!oCh>S2s7OUeI{Hb*B(K z8xgyDijEKO0y|cq`vYJen4a#BrV{Gyctf~Xq2&h4ajlymTD-j-5EBP0X^t+(Te`P> zL5UVXJRue;7@Q8^vH-)3fkL}=qcj-nwodrYuOa;fJw>+iZVw(@Y5!{(n)DgnMRn1y z+(936cXz)P4W2M*;JCQB#DRWuD=2B>U)PLhm3w!3Q~DfT^lff#0@D!G{owGhWVVX2 zg#|4fOjK;D)npWlxiq`pW2d(E~VxAum@;Y`4Ocu* z>#sIL;K6(kWQCEhY(dM5y6pNV)k=xVzT1>JLrDHOFd$|EGha!{2&J#`D(Y5UY2(38 z3$AlfMp|0L1ths1J)Nx?^7}OG`MDL_sfnGw-E?(unSTA(3U?5-*PM!+x-)vt0GmJQ z)~u8m>4RwjEdqdgJA7APU;ndlr_JwFCPv2cQ_m)YXdvRMofo@Hy;*<~1A7eB9@~0n z5l{a0*pk|)DVGd(Kt;gn@NIc9lQhap9u0*_ETrp;z2Y44 zK4k0rF18<6IBa%UDf9N3k6RftL!jCaZ)G;!KXF%(k$|Jyc#^kRgR$HUSi+B=9OwfN zRsMZQkAb}MCPfcW)#>~XlxMzM)YwfmI%}Fu0fu_(9=}g}xz63aj5g9TdT=Iu>v;nJ zCp80nb;=n*^~ZZph@Hi{#namHL1)T?vr9$oSKAk&>gww0qJF7Y7bjrh2^wBaHM^Jo z*=x8xrvX;9a$$iz3!J2ugI*?}!HvSS*Fm6~0J>V)+b24v19Sh@k9MvDMAg?f{csg| z*iGShYs~|`)w6o|;wSn=tTgp}6@ofG{`p^`wJ@@9aZMB>-UiEIrA3NfFar||apDL3 z7jOk&dvXX0hOc@72geoIEtP;V04daDd_M}@>%TdP#V{asEPnm``2u)Zpm%_}0<%$W zK{jxNBpdms+(pOBN_Z0AqoS%R?(WV5fj~e-R69%y-s*H-yRpgz8F#Rkva1XtRDA#p zzb5-xcm`lZz>t&(2oNjQ*q}Q*4NfP zI3@v_O(YAVKlKY}|8Lz<6kZEqbfgp%z(+b4A^UtC%;x*ffK|IbjMK))v!-6`e@k92 zLuf~Z$gZzX0TO72R%ncm@PHA)IGw;N$CVdT>mT2<0iv^M7`V z{^rc>p3t9d0Px{`=_8)o6^P&W%S>sy^HkkSinf3(g_WImlZ!(H@$DbKwr-scF?jPxiv zPaAtDk(iVg<#rbK&Gt{FJtSC5*sL|>-7n*-i7*k5WL=k zxj$5A*K_tI@wjho*qHd$D9ruaw{T8Ng}IWErp<57J$o8oqo9Nwm=^mHi{0sFL~ibD zgI9)|#7X~!uRYGa_pzO0kxDnZxe0^HJ@IMMz?i62FZyj06nyl)%)2-+w6eg(Us|un zs_S7-S6PRKwUk*iUSEU|>)E*G#n=1B|Ks#i=Tfwm0?y6}+R6qC=%H*b3mx}eQAsAN zWoVfxH193me715ecEQIK8U4`9MRXhhPhM&6e35Q1k!p<}GYABqZE(v+HQIxEB1N zyI}QOJ^?`eUR6@6PZr5&j`@U11N8X=j2J`F2OLr+Dr3FU7u2+RC%o;94XRm@B*{4_ zq_g;Uy!an;pI4Yo>eNTsPv%j^GzInVW52qbpKbdd%awc@g%p!uG(p5m{$J2BJjv&{ zp2VM7UN-YSYD6^xvt9bA;t`%jss}^jg(c{rqUm zVt~rDlr-qsEtRce(%Q(&Ob$ylH%WL&7MTCV#g18?Lw&E&$t!&q?uCV@_dJL{QAvys zgMlP}`gi;9N5QH=v?1vVjp1&=9K|4Js76P7^_N56ZcE6ZY-k;Bq8qoix>1Vh$Wcl^ z3B9K%3{R_jyK+t<8wHyNJCMr1ps|-q!&^E)tNqEF^%B0f9LA{TEP9*ZVLW@?*Kv63 zLH+r$;E}LPp%%BLC%Njb2T@>Ci{gdWt;-@PB*xz}U-L@ghu1I7JXwME61VmtLf_1Z zaOM*SyVr1PT)q1L0QHCq>IUQoHCu5BQqUv*O@DpP9MC+ZIsSvY1asYsTv3`sR z!M2~l=Tju3mq&nAYf?VPv3kxux^y}jaL7Pj%B3^kTg$Om5j7uhvk~FDTIQtu`9i46Rk6$`$C5fm8Bc4}NM~alO&OSq zB>7VLW(B_uv~I51lonPAKAlwoY%Kb<>??ptHS;~X=Lkz#S^|1P(eMFl}K6BggHs{N_~9a75W+_HOERL6&`*BGO; z7&8%^Xp0x8<>=v!Typ9CEZEH0`A|(KA@x2cX&B__wmB-%ENK*{C~f&2wsi+nfvhCz zgxmxy+b^01ArCK!F=9-i{i$*c>96DBTb~*<3e(Oi{M$X|JHyvPtsx;Tkaa4iUcCYYH};LjE{ewKZC*41Ud9k_c3Ym2bn-lUA3M0%XJ-ps6j z)7W%;1d7z;4CLeL{&||{HT)lG&;|NnFNr8*LwF3cGJUR-bnn3U`IqWW#pGZj*n7MQf(hQF ze0DvPTGogOI9>4cKkDhAnw0bD@IB~j+`aeT5XnwzwM=~KxUjNUnLuAe&z@Au!KGJl zmWhtXnZzQFabybSji`Vy^>uKf&7SOEt@Y^An^oFj&mLCU3(>1$I%=N_+KnfHha>*D z(FNu>-KV6v?e~_c$}w#!Sa68RX@tu2>owS02aU}z)l3UM|pOSV!}7Oa`EW8KcZ5wV#csO2khhzU3SoeRWLM)o~YRfP3}V~jXkHv9i2@3(ej z3p%H=HaS~wpR{bgM-~6S$q_~mz@`TF5}ko=ywJEnyhql-yj` z%AT0eg$-kRUp%t*(Lb)XKjS1q!-iEN$1)W~>c^_kv!j-sL@$A!MiYe@vYNmao#t7j zMA%M*)>mD%<@7!Vi%!LcZ){HYSfe8>Y5s;jzml0KGA=X=P59FhZ=V5qLYdD6!ThFc z5GZL^+P~!f)Ul=k>szeBQSRr6Kl#YwNor5;N$oI3AY{|eC$=Zm`nj)!rvr&9 zu7haTDbBhZK0=A3-$|6}oWW}3U*!ByIi0x&-jMvOq2P#GUw+Ej7PX}pEt7Hc^%c2@k|T?q1=9hzWY zJ&!~#33yt(PmVb`JZ^e?9#Tj~n%Q~EDqr>>xl4th?uLos>3}~6%7vj0IyH44y}}qm z-xjw!Au>92O}XS5yHL{OwAydaJ~^Sb2;b-(UigO|&5$!uYSMiAp>J~4z+o}4XU`Cr z-{DOhK+bx_6Df?|YbYvXiyLP1tvvKQZPD2yjUAkqjft^*X@7fO%WM>K$?Nbp%FX&` zY5rlMmoq~;Nl|LVnoWe5arAZUS*eu}<2y8?Iyw{BffXI9;<}-h%-roEJwa5zbo9GB zv-YBb3vn?gJETp>GVdAsUbf(gIx@YIvsMuoh$thBUVNMJWrTHNtuZBxmzJJ`gVw-J zTm0$`=}r|Cj{!#VE0~E$q4l+4pSV4Al_ViP@5S@LVLQ48c3+C#T}STku)q`t(o<=x zQ}$Z_2R79IZ`hfBoBcJHSGJb?eEeO@`?>~Zv2ucW=~?PwgQ8k0RuF&b?FUh*wJ7Ea zjXeWzt5p~=CpuZ1BJy+ecC(njO3er1)&UYxJXA;N z3k~D@(uy;*`z6&Vo-gBHbZPt!!7!)$rd#~aIbn|9^6jdNCD^~xGNx%2=%7#q8~5RL zSQ(U?RMz4rMTLu6>Kkk5l3_}uJ&xd6^dKEmw6R&zqLz!k1#RiUP_)~ zF9YrjBhEyZVvOp6#{MXCq^e11jA`eWM;Ig&m`TUqSx59j#Uc~Kc8eq1*D7ZwtRnG3 zcIk0=1u47LFCXksFwL~+k|#5GVGfkE4$x9F(Y*Fx!dYYb>EIT+w??b8&FkOt#OSil zl;m#P^4mll+g7TN0{DIbm}e2jSO-#se_81yr2TNcNw~c&Up?RJB;Yryspft1O>DnP3z6)v;IhUaJ5%X&)MQ-+YmRN$04$^W&p~ zzz!~tmNPZ8dGsz;QuEx}7*2oPA}Q3;3B6E~JE|#R42Hs1RCuEt+CP!{y7K}$+bFQg zBV(PA&ad;8IOY;Fk>J5Qs@q5WT6QU$*n4lzGT!ie`lsjF$I9zHvm+vWZ3{7&&KO1g zn#KP7zllTWkLO8?S(ND8KE^^_Rr~Z9pYuL?)(IM%(c7cG?`U`^!Ggt-U)h;xA$>M4 zSQBjd>D2XO(ZrN7S#lR+gMEI7DRJ=f*y%i4pC{2Y>kVaT$qigi>(1VnAanZF>zK;R zJjt04U_?Z^XT)GcIFZPMgRs75_7Mt$9herC=&?=Qp3-9UQPJ{Ba+~0}yzc7l${>kQ zasHw@-un*Ua2zYPjLm&v3pyuR!&w|?xrFdUX8)pl6ZDkJ2-|+*u0#jGz^aM2(2xAY zW;}~=os$V9Rs0t&{P#S)6Paea@!4cF_9i|Ng{+fO{qnvDp1Wb9*y1i?ZX{qonD@B-mg>hqykmjt23pQQI1O|jO4%0h-H(O<%d$JvS1K|^ETK2XqJjIxLz zDI}uS(dcyxQg`582Pdpjy0IF%C*rC$lkm@8 z`Yd>h#?dG7vJ?FCa!%>Oiq2f-)^Sm^3R3?~VeyelwQB|Y)kb9V7zk)Tf8`{nhnj@` zn&1tGDr1QNesjb}D_-BzAZ{!gA=0E*`_LD`Y1E3o*2Z1)LORQMlaCpRYF|Y{{eMqs zIDhaR8-3=#T=07|xLTgq;NhpBWEdNfyCBE@B02?Y=MKHOJ0IppK{PJQB}IlHPovn| ztNW4%kSZwfcQz!TD#80&}?3Xos zL_xMx!lE8ePIXFFz&jh8G5(X!!dFM}3e8I-*il^%-nIw?|D}>1hZZO1tT>8svO3SG zdhro^<9#uG#r$7J}UoYigaSabf8h7j^iu*r%4@@PL$dCIU>v$ zJ`K9W4}KsGUWrqdq+rd}v(5$Pi#V>kjtz9=`LrTbF^bWEh&LkP?N@vfrS4w^q}p{@ zTGgsrm#+jrl39lj(dS-8s6J4rW#HDUjS(zVITw_t)eZS?y1H!cI-i9oD!aNQ+>VvP zzay}zW)6wAxLnl{mAJFuzNPw&b$cgAu2&<+L_+Jy+7Szt@;@qmJS4{3cN$58Umw;v zcd5EQFNJ6iCI5goctO5njz zmA>Fao&U3dG&+hy+^=aru)-uXLkmi@8*I{;ryrr_oVmX?mhdU*GrS-l9)7+NZh8t6 zymzgk!)l72$>n97vRAfsa7cc$f+rCvrpYNWD?-`V632cp) zvCkKDb=|Gu6|_1d+3BzCctKVcM_~r-iMxM1XDIATVV+$kQF*6KL&swQ@pR6eG(Azx zqzD#}9@mpRVB8-En^E11-hk&)Qv3CsT%Hn4SQ*Tk(e4fcgV0Ca-RUXhZP;i#753!4 ziBJB`<}#rfs=eMBLgJX=LSzmr+y_!bf4iA}#;Pr#efxfjf+q1Ua($0K9rPy-=y(uL z=rulgkQ?~L>N#|NNA6ub3f((%p(3kSIn_|yF#6i#&d0(`%j!`v!S#Xcc=r(Rh2GOU z#p%r3e5NT+rAr764DFC+s3e*Ty{fNc9q}Qlpjy!UeOeXOedKE}N*AxNH!nglHaSc< z{S@O{FM56;ap3bbi3<9+$qpTn{xQR^^%GD<%IemI7a6DbCf-sB(}=BgKQy}hNcK?xt9WD&3SQ)K zF!}>MG(nD;xg^p(KGaEA`a3M8d3eGTMWmxrB=TB0NK{-&Zd&pe1P;BCbb5@~=Hn5` zu%gOjKJkbSt9;1jqemn$574Y6vWFxZ@NX#aQ3kySh)$u7A6Y$hEMr^$s};G%4wJeZ&v<8d)d5 zifij?HGVLh@MoVX55v-KQsnpJ{CGm}sc189{}3&3kh)vx;jjEncHg@uY3-(W_^=D! zkefk87Y0xRc~8+SAejnJ+DGc#eV1lfYKOIBo$N?Ou*}5niJ&U6Zn@?3-hHzk{>Im| z!&P6<-*D4u!CZrl8is9-PQhoX%;wMh&!}o3w#QL-_3{5TaFLYjhE(fTBszNK5F zvh!y#lqO?BE?u}ej1cR3`gtT? z@p%NI>2#I-pw(&1r*XkvAmX>AGCHzviNuR_enmq_xcoRUc_k>|c)HT1E4X8APy{?I z`PXTDIY0Sj?o&G#7J_kiz{FaNz7s?HJxeY}5>@>+sm9N>2%04`L<~FAkrykWJ2(=YK^H>c8onV8nL2heE$56 zh$m@IV?Q-yrEOUtWp!@#ztpr7&9yDL+!Mziy;wzd=C_4ZjkZ&uGZ84{1X+12pS^gj zZrtsc(y|pFvvO5nPs+}pmxFG1?;5F2(WESS;30YHhAyTH{qMxtxt*y_ zE)|33Z@xRqlPaYdxTWR}oJz&M0o!g}-74|&Rq*`i@)btLA%-Q_@{qvJ{bT8(MRI&6 zhQdb&M!M*QQwI|_tRyZ>$yCO%C-f+ozetk>YVp<+1tA}yGx^$sw;a5Xg~hap?j##t zUhQfhGl~;?>+CAVL+VU2+#U9%3*)WjtkRy}&XwvW*zI1OZVI*MG#-8&sa83b!t0#p z-s2MTbZ}z~>JjXVpiNV;Q~LVFtU?0iYO_tv7EwUD$Dl$YG8b&>{z%{8KpTB z7QB6s8WmR^HE`dLdaU^!omh2XD;5$-f3K+_`HaCrm{+$?l+z1iF-{fuDsUoMEBD=7DdC5ko-IR!BF?Kqj@-fQ*yl%qGjYeeWuYuL4sWGpr>W*hgJWJ`i=Y zPV1uoR(cSY;QZdOi_x!z(^35sE?*aJ@_@u+qANkQ1B?Ih4>8|Y<`d!!dwzjt-#fAz zvPM30J1{cmc4B@MXLs+I=in9h{O*$qrHHg@v+N@m_1~r4C><1Mf~O3zpEF0cq0AWT zKx0vJdpliPu#_vC?OXQhpJz|t34M?NbO1F;`#LDM{K>%kH;aJ>P$o2?{}`v%tR8k@ zzeQbrYLFk@-Ht#+z#=pUuU;FHe5}rL=xBfS9Cbq~l;pk^|M1{F0`97%e#XB~LNxfF zYQ0tutIW^ru9AOgXx$KRZe^YwDaG(=5D!{FQx--MbpWwAVD;gxcbZKiZq_S-8tXS= z_}x6Pn88IG9INZvp~0s9%I3ISD7Wz`mz_e)@iXZlkI5splrPp(rfFhjFABeeK|LC= z%39(s`U}JTnsbM3`WVnIiUJzKw5qm)+x2zDi*fEXL`Z+9>xd&MJVl~=Y_|}303cKh zpu2s`a_YDgr@m|A9BU9$h|-Cxq9w;J++6l7RLz{?o(L|g7{&q$tfI#!RhP!1Hp+~_ zfBDtq>CYc^^HkmQm%E)?k}8_U%e@!x5Yu8g2t4ijvV6gSp!T}j-FlDC{ty0DloFw( zJ+znUoW>W}0hej_ST$sOSy;tOcdZ`j=}4rfu-y%NUcPWtRPYMt(TD|Q?!EcIcqwGSTe@RQ*St} zNqa@Wf|AD@-dIHeagz9X%Pc3}Q(4=>4owS9>Vib9J4JYX!YiTkMO(SQMfYzsmk}CT zjdvi;J%dL2;a)IS?blRU=Tr|qv^wMe|T7w1Zx80D#MY(eb7tQuh;@wN24g#T)2 zt&&z4v+0MaGDcBhxeW1A z@$!tK)eV6w8+Jea*=BJUk--^q9sVPSn>mS$X(3HIb8InJ`EFITlR>RD3@MDd-n02q zuNl=__CDT_?zdr#y~z1Lb$w-6R9zdc3W&6?q*4Zgba%Z7h_nJj_s}rXJ%EzZN=k#Y z(w##|4&5-o5CYOO|anti9F~_j5n@V)&VYvNh?6(yQ!mF)o91 zK3bjvjRJhu1P~tRrGu+h}FKyuS;H+`vA`DB&1=6?5 zT1|@dw{@^5)_PSFpke)#XGvvQT(>H_A0r85VxK0e8P2Lnw5J7`bDLA*G*JD>7WnWg zAW1OE$+s-3y*#wNg?Z+6p+dWp2b4U%;miJHkfzO2>1QF0#5v@zn0#>iXp%$F0>)VD z<%ExM?&|;cLwHVc*!lIXp_A;Z=bdF#@w)#yK8`+a{UYQd$B(=l^gW9wac!a4R$j=Y zCtVybHsoLPj$H-{c6QR7HL8s465Cvu1W`+)eELH|qK|VE+_=^9w zBVO?%yKq4F&I1}vh&-#j#Nqy+J(RvlyV|3#PbA#XTYyx0Y>*El;~3NU)T1esQ*Em1ZgA5$2A#xy$?jvWj?q| z^?(SpinEDdz@qUL*_`AlU??l8^LETLD1-X>}8y}|N?1sZ5q)AuhiRBor}*Y6#} zAo#@&x#BZ-W+3}(f1%3(pA@}cRwZp?ca65n%H=mKI+hDgO@Hx+WA7Ws&k8P{1_y%2 zG}1aN$bQW%Vnut{Uh`BBB7P&o&($n;Mppp{tvZ|cI zGxXc`Dh1rs#gl&ju}-3-S#_!ZY2l}-EYmkqZzI0`&p|1TYGtgp=eJeXi( z2Y;F3`J|=@{+i0PBQn6I9A!Hrg_$&F4)0TXN>!hoAK(;ry2=J;+ABl4%3Hs(ri_yn z)PH60s{PDHLHB`fFplfbJcf@$rM4MJliVU+MeRGJ)g}=f_t_dfOib1cv}IOB(1(hw zUk)G6t2CNyL}ATv6wE!hSNY>6X+f5;0K37#ht{q}pN(ONplQVFG>C#=if*Z=*F1QY z%`LS6DMS#m$L5+L`(4q6>Z8H(yBE3AZfufNob)Yq6Z#B+tP>-hZ3v?UUWD$N?2LPZt}-)i@;>GRBT5fx$2knld4x#e3lJLSL3 z1{}sVzS=QSv6v;gaE`n~yFSF)Wf&K`1@gYZ?f$c6-*RGxIulXgOSR@JC?_NN~ZOM!4FUy(K=Kcs> zla`$VqD)=8vQNocZV!Bms|b{=XL^@aIXs%Z4AGX)*r3TV%E6tB#gvef+Hs55eUhavLdr2gQhvUwXb@r$O2#5|9i3hABX!h0W^X4|V4J@1BK8Qy@|FAm2P@Cai*BB>7D~P+UJ0POTn7rvq z`d7bZ73hh*!k>qm=E|>yCWwBQ185d#wl>F*qpYyKthe^+=Gp^yaI~y*of2L+$bpwv zNI;{t-buH`7#nVVwCM+7)Wz{pOEz^nY=?R#lw_6tcWSC-bd)#l4m>~m)P1xha&NAS z^GfkUd_awnjAaAY_ZO#scx8?R--};64s|ioO;7*JXu_R%(s%C5IbtHi9HjRBvb?^J zD6uPU{N+|=S3{M)G$&~GYgn76?ATLf6nH*v609fXx1%OvcVH>E%Djm$QYkYe3?<~H zbm7s_5NaEZ(rmH}5JB~cW|>l|e9N1rHuzI_-Jxy0UT501P}C#G8L|}F`+U;>RhHpx zEh!k_O0*}8C~BqZeDK_QY ztsC#+l+djD`i`tKAuQakY22`!q#oUxL1fcGEpeM&l4%F$&yKs?{J_qxVG&a`ZsxgT zCTX7z>z8ShyNyTi0FSzgxMBa{aF;RoO+wbS(BDK{4pcgPmwHtU}jD zee}TF7bEcKUdSZI1QYcrROX3(5UuR;lE~6!9C?Yw*5k#*8q$b7gGVi91u8&h($?c` zu&6OTn@iaBf)AfM5-e)WM{bQjLYtbuY zH3Xi^-0tWLGI9?nObGVaTQxP%8xAssw~TIKla`pWvc3R?YSndsU%AdWdWNygkUdIh zprV~j_ck_f?F;tPeB(^XcgbcZ(3_%sZ*>whMLGZfFDvP7s=h2z~H!cTD?sS6s z$TyC-9-f*1>WKbpjuV|rRV}ck|6K{Ff0KOvKV-t)okZJNqcG1 z!=87+c^TO`lV)`4bid#d?(xeFPN1SMZ^NO6&jW@b&sQTE{sV_i&1=j*%j=rOXkoxS zyKqQ*!=@*AA(FPpUs|3rw!lK9DdTG$p0m`9ymp_dWiI&Re|L26E!__ts`PB-h+Ly+ zxl-wwK=^424`@2dVV5rg%FAYeUdMrguIek+e>Cy@)5x%xIG(&EW+swpiYrvT-~5*j zO3L&0;YZ!+485cn-E9X_3o(Lj4ma8)$)$>_$V_~1m!T%2%I;S84k^*4a;0gWVJEn^ zyIgl!2f3@{HqkDFKUgL@w|UWRmx|Aq$BN*^O%>}u$^|t{>roON(Fk|LG#o)J8bC!G zXvzxU|CD-dD#6VSmaPPWdW`MwY1iD@u+muu7aZ}fx@#0gN?)Mz!Z*acW<}^-UU7#l zw*KXC47^}r3KdY%CAP}1+ca>~W2I`Q3vv2BE#W=W?QoA#hvju{Ut<)50$sMtmGYg( zAm}@{X~toNpbrQF+`Z|xNcP$sg7Cj&>B``}0v86lZdgxd>TA9WM*NlgcTZN;Jf_3A zzTwtBSn_c#Ka@G`Jln;1{!^4EceK!l|EeFMA`~W3B-_n0BgFET7F0yRD*E<2t)yfr z#CR?P!A95m)}*k~GF%9B zE_g-in4pDhShZ*2-oC#kR;fAGab49#HpQEiQ?p#Tiq*WObi&jLqDY}58Mo~TQ@K1+ z3fAVZkCxwJYJbb={hsfEzKXCmkKDya#W8v&xDVhQZX%&~cYdVst_Rs?12iNRs?2#) zk7#M=?Jq={b(LFLXd~=r3zy7Peh=@$h<6DYl-@}0>Pcy6C* zCLo#`n%cx){W$>B9Xsk}-z?J%ln003{ex{`j*}v~@@DTt3T{4*jl{hHNdgsRE}sWP z8$@po?xkLf_ZSh*5`DuK+Aub2W-K6@fa%*=`Np}9To?RiWmNy~lgUwzHPDC^hN0R|6U1j~6o6@<*WX&*?wAH!d; zL)VQQ2o}u=y!|ty9(%su*8DS@0rc`;&avDIQfGzbOqUC&TRva>y_U7m|)w!W#Wv-KURjj<& z{3tPkWOKiioqUoT8@$x9PnsJ(#>~!IfZ#Z6M?LOO3+Ymo{`%ZQVl2c2^|0q8AQsOn z(0i%iEScorBdkv`@c;nzU)1UEg3EV#M~UvviCCtTWq5#tf^^kn=M&LfpPKCZv`5z* zisay#ZXuPaO@y6yC?<#NS5Z?X5_CC7-+&U`Sc@egUY! zy#KB96S+Lz8hp*Eu|Pcz+3Gd^61hjw;i9o#d|Aey1(HbcEd;`>jH#KNLuZzIQzPH% z(umJo5&WNuKFF|Z$764C;`i&{?_)h~?LsCV``@sw{rGzT@Z=-4jPNHz5~AxnY5-SM zvfm{j_Ezlec1>S&j-q7IX&zNi;wC^OMEROT+q=j!hq1hC(qOrGYyTm;l?D5QA(n@f zvR59~w>^@sVawXURqnqwwYb1kwG4l^>finQ{mled8gDkUwlh03@V%knunu<$@I~3V zyvEmM@{WoM|LtPs`&}!_NpGpi=%JkYp0$tP;($)1S9deJL>oacE#R8JDGXQ}QN~A& zYyVJT9{p7H7o;f?OR4A5_-@)wTKO83$=zAw-}lszJQ~Ymnz{3qoA&H-qcOg*Es9Lr z`t|sGb%J^ht4q-9nqYI5zc;z_a^{m&VD&W^wO;6M@-xHa(EAP5-R>L243Dw;&@rO+ zwctz6B9ds$Ap)tB2Q9Z6ZsAZqIC^vWn9uj_x82x1KyURoYy0H09VLU`?MHqh1$%=T z!AamY?Oecofa2kLZeHBf8}2!deOCJe2?PE2q)iZb%s>L5Tjj3=h<436 zE$qO0^ty)}(fd>ZVA2TX!8d8}vhwC6QNdd0>nM%~T0&NR?uMzKT!dpfY-1Q6NqK&}|*}m5|H6*j_rU=TQHHEBle%{BU31v4t-6 zw^EE431PJJvc9C8_nD9AVPJZ!WJxgeNYMwYe=5^x^CtH4I^DY6NYZynQso@ zo6;=L%?>i4M(7~bS~j}{ySNfL9Z)|!7sT8W)G0Z51^A_XKsfA2Ah9yrXC&KmAD`Ys zjyR*MKesUaF^lYsd6uUk^v#{A@ICSsBJd5=&uHvJG*pb!oRs0j9Ba=NX zXZ_iBh~Zc5I#=`!&4^ki$Y9v11xJu{T#-&>a#N6*+AW*~_lsY5dtq*g9^P zzGBIVc1Lxr>JF+1ef4?MTrAKlN|G%h}KPfqB zMQQIbCyiL|6zuwuI3`OUe$E*y+4lwlR zRoeD^gM>uXWby+18T5LhL%SDS(sv76Pq2#pAuQi=9TRR3`_cK~pM9LfZ+6KY`J7He z$HXzAL6R}~>-dMn5e_i>j|q7q5zHl5JALY^2|g0qmkb`d5pXf|eeZXv6HkI+^^y;>QfaLxdfcX<((NNj~ml z8d|dLh8Rw=74=FQ37-$8e%G$BtNAGhA7wc`tP?=;lqdFXac?7Cb3it9Mb19Uj$rBl z5c3Fn`Ry-JhQ-yWso%)=-2Ce2#=5)^MWaCR3YcW~r?k607=A{v`OWD?E)~_ob?;JG z2mR#^AdTku>H4hypsqx2f|TBLD|oU3dR(R=~!ZUof z>3~I_G|<@OofmE2j1e%pzOtnebN!HhWpZ}6dqaQhwX5viTr%5an;DoRdo>Y%UHZ_{ z80E$WweDfH2h75WacKA#b`&^PfsraLc~z8?-eSG0Iy`vq;4)jEF6C=3EIC@NEPMOq z^60RT>b0@t_0o4_r&^e*WJ8G2>4uz#*&fBM;I2H(mY;8sa&tb=9?qClKXH< zPsdMhUmc&@qvHLb|8&<(SJ$U;iurP8oEJ9gAT$VCfz<%)fHujCU+g#b>2v7DV!OOWT9vDz2a^)~%<>2^gSHbP_)g?qh1S!as~_6RVDt4y}}j#-x5U4`w~dR$Che?b@O zz|LnIH8jmI?$;+n@wCoRn}h(SLG;{JHqd>D9>I0n|DNF)7%fr9EAj5>5~?*yrKZF_ zuY{*V3wHWI+(){}@h2hDcjLa~K~|%DzW?L7H|o98fc=PkW?9F@)xJ3W<7=t8i&Jo| zivGPQdsdom3m2#4^<(-~LEqhuPkJ61f>Eh!*mv|Tgk-x*1`B)41~vl2$B#HcWx?igW&GOk*8 zD-ck0_6az`#KA6RjFRJ^+wYtPa>UQKt3w4d67ui|hQM=T@YLi(kY}TEr{m8W;e8q` ztUS=|ECVR!iWYE!sOi#63Cg>#xbIfogq!b7)gChi))g`<0tP(_0@e$YX=hxT*4Fg& z`~b8o$-mKgJCLR~`PLxG+{!M7w>j})q^7L&&9;p;@}ocsj%%*g*~>AJ>?{O=5sqaV z@6DNQSSp}sFp0xS4H2J)mV>Wx;LUCIuMwcplYEmXVEVeEN5({Z5KKdy9_)#7U8iWh zZU^xU<(&b*c)W4&3GU8MN@ZWPZeElKQ8mcS_xl*8A3Vq(i4Hp|PnR$hhdu(gmO~_5 zh6LQ~4MWTeW1R1(JOzZbvUyS%;~g+-;r0i8OJf9da?}9=pOl2mM)7P|cr+~3m+EWY zEQRfxe(z%%I=OMyW@GZcyJ+v3@r4L+d-M5nc7bC1)dgDWxA?>vLPNQ2Z}q2G8|P09 zy%VPv!~rE#5*ni!NhUhSm5*OwKtlL&`zsLStoj#*iQ!vp96VhZ) zDJGjy3MN6e#GY;9Lyeqaet~|ztF-tgJ=7V=OXESl#AywH8g64PWN~m{XIyiQLi{U4 zugJQHNIBE7SDx|0GE zYDtQmUMk<5gm-`GON+!W&W}+FkBQcyG!=rLh-#nKvIkX%?MLp0Ckp#Gz7O5d0RjYi zzh5fAGvx3>DDNnXl~t1Fl6elTjCV?T;db}EJIKcB7IxVb!|U#Hw4-abg~#x3{)2_l z&8~iB8({eJ=^s(nALQB)T6=+bGvqv?u(;n;C+stt*-*&i&eXvNWANe(?8(|b$1K(E zY(x5BO&59e`C^H(osE4LRlwF+6Z99^vlS_fO8$c)>u+F)I{S=Lm~&#V=lWr1#knnn zDkXJkJ4kAhZ(<)9NSlJ9TDH>0u6s7rfZC|a4M~{SB^Auv+QrngnWftYHk8)A22klk*NFS0!$0{>f z*%stgXEAc@>2UZ^L%6yg+X8g8l(gUb&_)+`^?vRu8C;&xuExFU6M>FyMd#M|=W?m)QUO*@+R%c7PqVBBUB-Y*u z&sG}jfBRWJE6&tLUkbW+8TL*xByW0e3qP5ZPO5*}t37P=uUhLp37-1Dl# z0eCcuH74U-aq$~$`R)!8z!b#D@3pqjnv} zR=K2C)W!T3spw($xIkA{wxyTn5y~3qG4^q{&n>Kp0SwRfOjFd&*0iuV036C<16{A# z(-*RyE40C{x=;IY-4BL$l?nXwiv20PLsX0wt2^@176*%-2da;!1tca#o(cNc2*Gw+;_9Ikhb-D4vZppt3{QKw}m;x`|9vLQ5G6U2QNu2#iA ziCQd)w6n7Padeq^T+blJ>OT;7%NZv+EJB(kNq4QO5R_p9#~1in=`@sOd3RLxUMy;MQQN>^N==n9Uf-c{UT@Oz(2gEgHFbS- zSbO+fWP?jY0;j9Y8*%r63fII)IlImG3cz@N&A0yuWSBq-#mg_+ofMwP+)qB;T$nb< zzxr&4)!BNqP-c3mW6@Kh*UUe;Z~I6XnXARYYE@L2!;+F`?+^iP>!@M>M!C~a;q=jH zOk0sLUM6d}i%Wvvxid|X!2^gR+(vg~?l~UtJ}-0#vdgVDvB|ryRS3Ap0oQnR@W9!o zLh_a^&_oQ;A&gK0#x*Xhe@RVxW^_+Ldo}@Ivxst|-SN7FLm=4TEujNu+*8GX$`}ap z@@82iJf;#VhK&k1ZAve>_<``Bi<4a;(-N{IyPzt@YzrC2U%Av5c!Fw5)eV zDOpqGjT!!pgIAl`2NX$A7wW==HO~k3lv%BcrNfMyx;6&Q+Ay|zdkS6J@YCnp0KZ* z8=jPLmR8oLHxqI^en9%Y?u!mp>XS75KIVVH3$zvGk`As3h&B$qYpe zq+E@Ee_Sa&KSQ#$bs8H6xJJ$WrSrYV4->q`HOyv))rOMuG9ilyCQgSEzg5)bMT(rT z)7n!&J0%H@%4)0~d81x$OsGJyDILlF2gX(1!nIC;))gIGUhAoarinY}%c0{Ns86_UaC}rxT{n*qN4sC@ksW5)zPCMLq_amwiM<3cnjd_ty*%0;tcpZl=sZd$zFiO;H*l z-`$4PT~=m9L0{hV!bo3%4!}V1KF{TkZyq`>hLpTIoLR0|su2epj+u<%nhY~5XDW}r`jUETnI))xw*qpQ?@&>L^ zb|SsNrR1N}#^E=7Qc@alg!z3`>{wBXR2`|WNrI%z!fhu@E7UqF$h>PyR$@u!dw~$J zi_sEuWxE%n$mHp9VlkPRdJaUOfD*?BH4WIx%wHb}R*u+RirL@2m~Zx^1HaspwBRmo=S>~+Sv7$d+v-E=p?$po@%Rk5n@A*jQU|H>*4bB${i z`p3!%`ebNt{l|h!k^7kp88$T8+EYPZO>Lkb??p(Vu^|- z`oOmIHfI{Lh>D4Droa{@t!D`$$87(=c!B8J+kwgNpm_?AI|1SV7oN6k@7iH)z51Uk zc3W1fey52U%ZVI>HwhJhiVzK+M5FBeRsn|3S{Wp~-e2w{2o62Zt@T`5#0%!oUo*Pu z55W{)U-6nR=}`kIip#XrszP60EyQX?J$l>Zy1eplQtXo`R}Wx0O!N!1lf4~D3-G4H zV`ksOHEv>BQ8;bN6x!CvqlgVET4TDG;0oQuYCLVZIt2j_<8&6788GHYhr204Q|MoL zX8^iN_uW;7UG|wgV&xHQawjml_=RQepUp)L;!d>p_d%E zzA~~S!;g0we!qT-X6Q$r#;fjc$hnQ_H)6=TH^T_8$0+IZZ6R1jfELTeugL5r?&}Ye zlV1DjL(>?tUAqr}Vp4|h_B-FBO8TGW-nFHh!dhl(MfSz(01W4>Udg8k8m@Oklk31M z3Q9{JC(18*0n!6<2B3GH-90%mcEDP{M*Wbu!W6Cxxg9?MaJhS&%{~vH04;k2)-}*r zr@KO~PuFZIda}?QAMClxmR<^MW-eh~YCGMg_NeEL0wt@G*OGqe8RxavLDGOBUBu`R zXEd~49~-quJ>6JbHxN@@v57=Ob*K1Hp>oGgQ#DaI-Lt^LC7?9Uo0E#S^rkD#u|x%NsBf#o<5J>mAO%Zf(F>g;y98oo z&d=z594y6tSro22BLQ#%FNHsnAG+O^HeNDZt9N_GCFTaF64#qLxJc1b+2K?9P zTG)@Rz4Rpjq!IGUiw11CzLC0~k+ic9IrWr);~s6AOSNESN%e=W*)ZAYYFKr;-)WLu zy}cY|X$xW?rF+oH#5hoiv2)Fp-K9pL%+r83%{IlV;JX>(Op|9L=MZS*{aw_tHHl~w zWTXkpo}OO#0l02EJNxA*W!r}-sU}_msw_#FK#t&AOk}rb)lsfho6(e&7qc10Mr-?M zrV;{ROJKri<)vu>B7X8J0gcL%+z;RMMHZ^+XHl2D^bO&1Cw8V|4HUYYTEvy~^?tbS z_Q-z?%%dRGx(=!F0WgS8mB9Fo_XH~g>!_Mng1-ZE$R^*N#gp>2;i)1R@*E*L^~1nu z4N>pNUau4e1Y!V8Q8i(7%1PF3v6paEH4eH-odD?3KiV*Vlv&Rx3}fas$zov%$pI%c@dM5XV6Jz>bznMjG{$;TYHr2wPTI1gUET zr$!d^-3<)A^}s}sNd74(O)lAtOV|!A1em+n7DAvm%b$%BDEfFU<#<4mJ%=y(gEE~r@D85j=GO} z$yJYl+Rr#ZIf@-~Cfnz5_M|MnX$<-A0)jvMPRem_iagOsvB4mCHp7E`u;O1P#S_5S zzg15%Uzug(Ad0N4Dc4lFIe_VR29iClrG-N64mdpps!wzK|2q*!vJExQnlA-h;-lH9xr%vi(=d%atLetLsd#HpoM6E z4=dF5^v<;aIlSgplAmOFPf8|$V>4RL8(S3r@0mZqxeUUt7|~lC_I;(Ea* iQ}zE0fY_T^TX_Ee2k1Cn+ye&Ol9yGHDS2t^|9=4YI@OQ> diff --git a/docs/images/pythonpoweredwidth.png b/docs/images/pythonpoweredwidth.png deleted file mode 100644 index 542fa7c3cd36d7c32223eda7f382717bd45a90f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15445 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 P1qjlT3KHdF1_A#EDk~OL diff --git a/docs/installation.md b/docs/installation.md new file mode 100644 index 0000000..4ab308d --- /dev/null +++ b/docs/installation.md @@ -0,0 +1,67 @@ +# Python Logo Widgets — Installation + +## Requirements + +| | | +|---|---| +| Python | 3.x with Tkinter | +| Dependencies | None | + +Tkinter is bundled on Windows and macOS. On Linux: + +```bash +sudo apt install python3-tk # Debian, Ubuntu +sudo dnf install python3-tkinter # Fedora +``` + +## Install + +```bash +pip install Python-Logo-Widgets +``` + +The images are packaged inside `python_logo_widgets/imgs/`, so there is nothing to copy +alongside and no path to configure. + +## From source + +```bash +git clone https://github.com/willtheorangeguy/Python-Logo-Widgets +cd Python-Logo-Widgets +pip install -e . +python -m python_logo_widgets +``` + +## Verify + +```bash +python-logo-widgets +``` + +A window with the Python logo. If it opens empty, see [Troubleshooting](./troubleshooting.md) — +though the widget classes are written specifically to prevent the usual cause. + +```python +from python_logo_widgets import LogoWidget, PoweredByLengthWidget, PoweredByWidthWidget +``` + +## Adding it to your project + +``` +python-logo-widgets +``` + +in your `requirements.txt` or `pyproject.toml` dependencies. It adds no transitive dependencies +of its own. + +Note the licence position before you do: the code is GPL v3, which is a real obligation for +anything you link it into, and the images are PSF trademarks under separate terms. See +[FAQ](./faq.md). + +## Uninstall + +```bash +pip uninstall Python-Logo-Widgets +``` + +Nothing is written outside the package — no cache, no config, no data. diff --git a/docs/internal/known-issues.md b/docs/internal/known-issues.md new file mode 100644 index 0000000..eae97cf --- /dev/null +++ b/docs/internal/known-issues.md @@ -0,0 +1,61 @@ +# Known Issues — Python-Logo-Widgets + +Concrete defects and gaps found while writing this repository's documentation in +August 2026. **Nothing here was changed** — each one needs a code, configuration, or +licensing decision rather than a documentation one. + +Ordered by severity. See [`docs/roadmap.md`](../roadmap.md) for the narrative version, +which also covers deliberate non-goals. + + +**3 open:** 1 high, 1 medium, 1 low. + +## 1. GPL v3 is asserted over the Python logo and Python Powered badges, which are PSF trademarks + +**Severity:** High +**Where:** `LICENSE.md`, `README.md` (qualified in this pass), `python_logo_widgets/imgs/*.gif` + +**What:** `LICENSE.md` is the GNU GPL v3, and the README stated 'This project is licensed under the [GNU General Public License]' with no carve-out. The three bundled GIFs are the Python logo and the two 'Python Powered' badges -- trademarks of the Python Software Foundation, governed by the [PSF Trademark Usage Policy](https://www.python.org/psf/trademarks/). The package is published to PyPI as `Python-Logo-Widgets`, so the images are redistributed with it. The credits table names the PSF, but as a project credit rather than as a rights holder. + +**Why it matters:** The GPL grants every recipient the right to modify and redistribute what it covers -- which is precisely what a trademark policy restricts, and which the author is not in a position to grant over someone else's marks. Anyone taking the licence at face value could reasonably conclude they may alter the Python logo and ship the result, which the PSF policy does not permit. This is the one repository in the sweep whose *entire content* is third-party trademarked artwork, so the mismatch is not a corner case -- it is the whole package. + +**Suggested fix:** Owner's decision, not a documentation change. Options: state the split explicitly in `LICENSE.md` (code GPL v3, images PSF trademarks under the PSF policy, redistributed under the nominative use the badges are intended for); add a `NOTICE` or `CONTENT_LICENSE.md` recording the PSF's terms; or replace the bundled marks with the author's own artwork and reference the official badges by URL. The README is qualified in this pass; the licence file itself is untouched. + +## 2. The privacy policy and terms describe a service this package is not + +**Severity:** Medium +**Where:** `docs/legal/PRIVACY.md`, `docs/legal/TERMS.md` + +**What:** Both are generated boilerplate dated 29 August 2022. `PRIVACY.md` opens 'This Privacy Policy describes Our policies and procedures on the collection, use and disclosure of Your information when You use the Service' and defines Account, Affiliate, and Personal Data. The package is an offline Tkinter widget library: it opens no network connection, creates no account, stores nothing, and reads only three GIFs from inside its own installation. The README links both from its License section. + +**Why it matters:** A privacy policy is a statement about data handling, and this one asserts handling that does not occur -- accounts, personal data, disclosure to affiliates. That is misleading in the direction people do not expect documents to be misleading: it makes a package that collects nothing look like one that collects something, and a reader doing due diligence on dependencies has to read seventy lines of source to establish that the legal document is wrong about its own subject. Boilerplate is worse than absence here. + +**Suggested fix:** Delete both, or replace them with two sentences: this package collects no data, makes no network requests, and writes nothing to disk. If terms are wanted for the PyPI listing, they should describe a library rather than a Service with Accounts. + +## 3. str(files(...)) assumes a filesystem path, so the package breaks when zipped + +**Severity:** Low +**Where:** `python_logo_widgets/widgets.py` -> `_load_image` + +**What:** `_load_image` returns `str(files("python_logo_widgets.imgs").joinpath(image_name))` and hands the result to `tk.PhotoImage(file=...)`. `files()` returns a `Traversable`, which only has a real filesystem path when the package is installed unzipped. For a zipimported package -- a zipapp, some frozen builds, an egg -- `str()` produces something that is not a readable path and `PhotoImage` fails. + +**Why it matters:** The rest of this module is careful about exactly this class of problem: using `importlib.resources` at all, rather than a path relative to `__file__`, is what makes the widgets work from a wheel and from inside someone else's application. This is the last step of that reasoning left incomplete, and it fails in the packaging scenarios a widget library is most likely to be swept into -- someone bundling their Tkinter app for distribution. + +**Suggested fix:** Use `importlib.resources.as_file()`, which materialises a real path for the duration of a context manager: + + with as_file(files("python_logo_widgets.imgs") / image_name) as path: + image = tk.PhotoImage(file=str(path)) + +The `PhotoImage` must be constructed inside the block, since the temporary file may be removed on exit. + + +--- + +## Also, across every repository + +**`.bandit` is present on disk but untracked in git.** Verified in PyWorkout, treklogger, +skyscanner-cli, booking-cli, piggy, and aibot — the config file exists locally in each but +`git ls-files` does not know about it, so none of it reached GitHub. + +The August 2026 security sweep therefore looks complete locally and landed nowhere. Worth +checking across all 44 repositories it covered. diff --git a/docs/legal/PRIVACY.md b/docs/legal/privacy.md similarity index 100% rename from docs/legal/PRIVACY.md rename to docs/legal/privacy.md diff --git a/docs/legal/TERMS.md b/docs/legal/terms.md similarity index 100% rename from docs/legal/TERMS.md rename to docs/legal/terms.md diff --git a/docs/quickstart.md b/docs/quickstart.md new file mode 100644 index 0000000..4b2c1e4 --- /dev/null +++ b/docs/quickstart.md @@ -0,0 +1,70 @@ +# Python Logo Widgets — Quickstart + +## Install + +```bash +pip install Python-Logo-Widgets +``` + +Nothing else — Tkinter ships with Python. + +## Embed one + +```python +import tkinter as tk +from python_logo_widgets import LogoWidget, PoweredByWidthWidget + +root = tk.Tk() +root.title("My App") + +LogoWidget(root, bg="white").pack(pady=10) +PoweredByWidthWidget(root).pack(side=tk.BOTTOM) + +root.mainloop() +``` + +Each widget is a `tk.Frame`, so it behaves like any other container — `pack`, `grid`, or `place` +it wherever you like. + +## The three widgets + +| Class | Image | Typical use | +|---|---|---| +| `LogoWidget` | The Python logo | A splash or about screen | +| `PoweredByLengthWidget` | "Python Powered", tall | A sidebar | +| `PoweredByWidthWidget` | "Python Powered", wide | A footer | + +## Background colour + +```python +LogoWidget(root, bg="white") # default is "black" +``` + +`bg` sets the background of the image label. The badges have transparent regions, so matching +`bg` to your window is usually what you want — the default black suits a dark window and looks +like a box on a light one. + +Any other keyword arguments go to `tk.Frame`. + +## See them + +```bash +python-logo-widgets +python -m python_logo_widgets +``` + +## The older function API + +```python +from python_logo_widgets._compat import logo_widget +logo_widget() # opens its own window and blocks +``` + +Kept working for code written against the original release. New code should use the widget +classes — they embed, and these do not. + +## Before you ship it + +The images are PSF trademarks rather than GPL content. Using them to show your program is built +with Python is the intended use; see [FAQ](./faq.md) and +[`internal/known-issues.md`](./internal/known-issues.md). diff --git a/docs/roadmap.md b/docs/roadmap.md new file mode 100644 index 0000000..a0b750f --- /dev/null +++ b/docs/roadmap.md @@ -0,0 +1,57 @@ +# Python Logo Widgets — Roadmap + +Direction, not a schedule. Defects are in +[`internal/known-issues.md`](./internal/known-issues.md). + +## Where it is + +Three embeddable widgets, images bundled and resolved correctly, references held properly, the +original function API preserved, and tests for both. It does what it says. + +## Considered + +**Settling the licence position on the images.** The most important item, and it is a decision +rather than a code change: the repository is GPL v3, and the logo and badges are PSF trademarks +that cannot be relicensed that way. Stating the split explicitly — code GPL, marks PSF — is the +minimum; the README now does, and the repository's own licensing should follow. + +**Replacing the boilerplate legal documents.** A privacy policy describing account creation and +personal data collection, for a package that opens no connection, is worse than none — it implies +data handling that does not exist. + +**`importlib.resources.as_file()`** instead of `str(files(...))`, so the package works when +zipped. + +**PNG instead of GIF.** Tkinter reads both, and PNG handles transparency better — which is the +one visual rough edge, since `bg` currently has to be matched by hand. + +**A size argument.** Only integer scaling is available without Pillow, so this means either +bundling several sizes or accepting a dependency. Worth deciding rather than leaving as an +absence. + +## Non-goals + +**Pillow, or any runtime dependency.** A package that draws three static images should not pull +an imaging library into everything that uses it. That constraint is why the implementation is +seventy lines. + +**More logos.** The Python marks are the point. A general badge widget is a different package, +and one without this one's trademark complications. + +**Anything beyond display.** No animation, no theming engine, no state. `bg` and the standard +`Frame` arguments are the whole surface, deliberately. + +**Granting rights to the trademarks.** Not possible, and worth saying plainly: this package makes +the badges convenient to display and confers nothing. The PSF's policy governs. + +**Porting to another toolkit.** Qt and GTK have their own resource and image handling; the value +here is specific to Tkinter's `PhotoImage` pitfalls. + +## Contributing + +Issues and pull requests welcome — see the +[Contributing Guide](https://github.com/willtheorangeguy/.github/blob/main/CONTRIBUTING.md) or +the [Discord](https://discord.gg/eAZZJzhHrW). Code contributions are GPL v3. + +Please do not open a pull request against the trademark question; that is the repository owner's +call. diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md new file mode 100644 index 0000000..52933d6 --- /dev/null +++ b/docs/troubleshooting.md @@ -0,0 +1,97 @@ +# Python Logo Widgets — Troubleshooting + +## The widget is a black rectangle + +`bg` defaults to `"black"`, and the badges have transparent areas that show the label's +background. Match it to your window: + +```python +LogoWidget(root, bg="white") +``` + +## The widget is blank + +The classic Tkinter cause is a garbage-collected `PhotoImage` — but these classes bind it to +`self._image` precisely to prevent that, so it should not happen through normal use. + +If it does, check you have not reassigned `_image` without updating `_label`: + +```python +w._image = w._image.subsample(2) +w._label.configure(image=w._image) # both, or the label keeps the old one +``` + +## `RuntimeError: Too early to create image` + +You instantiated a widget before creating a `Tk()` root. `PhotoImage` needs a live interpreter: + +```python +root = tk.Tk() # first +LogoWidget(root) # then +``` + +## `ModuleNotFoundError: No module named 'tkinter'` + +Separate package on most Linux distributions: + +```bash +sudo apt install python3-tk # Debian, Ubuntu +sudo dnf install python3-tkinter # Fedora +``` + +## `FileNotFoundError` for a bundled image + +The package's `imgs/` directory did not install. Reinstall: + +```bash +pip install --force-reinstall Python-Logo-Widgets +``` + +If you are running from a source checkout, confirm `python_logo_widgets/imgs/` contains +`logo.gif`, `length.gif`, `width.gif`, and `__init__.py` — the last is what makes the directory +addressable by `importlib.resources`. + +## It fails inside a zipped package or a frozen build + +`_load_image` returns `str(files(...).joinpath(name))`, which assumes the resource has a real +filesystem path. A zipimported package has none. Recorded in +[`internal/known-issues.md`](./internal/known-issues.md); `importlib.resources.as_file()` is the +fix. + +Normal pip installs are unzipped, so this only affects unusual packaging. + +## The demo does nothing + +```bash +python-logo-widgets +python -m python_logo_widgets +``` + +Both should open a window. If neither does, check the install placed the console script on your +`PATH` — `python -m` works regardless. + +## Tests fail on a headless machine + +Tkinter needs a display: + +```bash +xvfb-run -a pytest +``` + +## The image is too large for my layout + +There is no size parameter, and `PhotoImage` scales only by integer factors. See +[Configuration](./configuration.md) — and note the trademark position on modifying the marks in +[FAQ](./faq.md). + +## `pack` and `grid` conflict + +Each widget uses `pack` **internally**, for its own label. That does not constrain how you place +the widget itself — mixing managers in one container is the error, and these keep theirs inside +their own frame. + +## Still stuck + +[Open an issue](https://github.com/willtheorangeguy/Python-Logo-Widgets/issues/new/choose) or ask +on the [Discord](https://discord.gg/eAZZJzhHrW), with your OS, Python version, and how you +installed it. From 267c9e6d1922aaa53f0c657ae24ef11d9b09ac98 Mon Sep 17 00:00:00 2001 From: willtheorangeguy <18339050+willtheorangeguy@users.noreply.github.com> Date: Tue, 18 Aug 2026 18:58:04 -0600 Subject: [PATCH 2/2] docs: state the PSF logo warning as settled, keep the GPL licence unchanged The licence file stays as it is. The README now carries a prominent warning that the bundled Python logo and Python Powered badges are PSF copyright and trademarks, governed by the PSF Trademark Usage Policy rather than the GPL, and that altering or redistributing altered marks is not permitted. The documentation index, FAQ, and roadmap record the same position as decided rather than open. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01TtaJBmFDK3GcSyuhSuZ84R --- README.md | 6 ++++-- docs/README.md | 10 +++++++--- docs/faq.md | 14 +++++++++----- docs/internal/known-issues.md | 26 +++++++++++++------------- docs/roadmap.md | 12 +++++++----- 5 files changed, 40 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 20c1b35..288dfc1 100644 --- a/README.md +++ b/README.md @@ -112,8 +112,10 @@ Sponsor [@willtheorangeguy](https://github.com/willtheorangeguy) on [PayPal](htt ## License -The **code** is licensed under the [GNU General Public License v3](https://www.gnu.org/licenses/gpl-3.0.en.html) — see [`LICENSE.md`](LICENSE.md). +The **code** in this repository is licensed under the [GNU General Public License v3](https://www.gnu.org/licenses/gpl-3.0.en.html) — see [`LICENSE.md`](LICENSE.md). -The **images** are the Python logo and the "Python Powered" badges, which are trademarks of the [Python Software Foundation](https://www.python.org/psf/trademarks/) and are not the author's to license. Their use is governed by the PSF Trademark Usage Policy, not by the licence above — see [`docs/internal/known-issues.md`](docs/internal/known-issues.md), which records this as needing a decision. +> ⚠️ **The bundled images are not covered by that licence.** The Python logo and the "Python Powered" badges are copyright and trademarks of the [Python Software Foundation](https://www.python.org/psf/trademarks/). They are included here under the PSF's [Trademark Usage Policy](https://www.python.org/psf/trademarks/), which is what governs their use — not the GPL. +> +> In practice: displaying the badges to show your software is built with Python is the use the PSF intends and this package makes convenient. **Modifying the marks, or redistributing altered versions, is not permitted**, whatever rights the GPL would otherwise grant over files in this repository. [Privacy Policy](docs/legal/privacy.md) · [Terms and Conditions](docs/legal/terms.md) diff --git a/docs/README.md b/docs/README.md index ca45271..11e0a2d 100644 --- a/docs/README.md +++ b/docs/README.md @@ -27,7 +27,7 @@ python_logo_widgets/ ## Before you redistribute this -The images are **PSF trademarks**, not GPL-licensed content. +⚠️ **The images are PSF property, not GPL-licensed content.** The repository's `LICENSE.md` is GPL v3, which grants recipients the right to modify and redistribute everything it covers. The Python logo and the "Python Powered" badges are trademarks @@ -38,8 +38,12 @@ to place under GPL, and the policy restricts modifying them in ways the GPL expl Using the badges to indicate that your software is built with Python is the use the PSF intends. Treating the image files as GPL content you may alter and redistribute is not. -Recorded in [`internal/known-issues.md`](./internal/known-issues.md) as needing an owner -decision. Nothing here has been changed. +**The position, decided:** the repository's licence stays GPL v3 for the code, and the images +carry the PSF's own terms. The README states the split, and this page and the +[FAQ](./faq.md) repeat it, so nobody has to infer it from a licence file that does not mention +the marks. + +Recorded in [`internal/known-issues.md`](./internal/known-issues.md) for the record. ## The legal documents diff --git a/docs/faq.md b/docs/faq.md index d4f1877..2dcabd5 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -12,12 +12,16 @@ to them. ### The repository is GPL. Does that cover the images? -No, and that is the problem recorded in -[`internal/known-issues.md`](./internal/known-issues.md). `LICENSE.md` is GPL v3, which grants -recipients the right to modify and redistribute what it covers; the logo and badges are PSF -trademarks that the author is not in a position to license that way. +**No.** `LICENSE.md` is GPL v3 and covers the code. The Python logo and the "Python Powered" +badges are copyright and trademarks of the Python Software Foundation, included here under the +PSF's [Trademark Usage Policy](https://www.python.org/psf/trademarks/) — which is what governs +them. -The code is GPL. The images are the PSF's, under the PSF's terms. The README now says so. +So: the GPL's permission to modify and redistribute applies to the source, not to the marks. +Display them; do not alter them or ship altered versions. + +The licence file is deliberately left as it is; the split is stated in the README, the +[documentation index](./README.md), and here. ### Why is there a privacy policy? diff --git a/docs/internal/known-issues.md b/docs/internal/known-issues.md index eae97cf..75f337d 100644 --- a/docs/internal/known-issues.md +++ b/docs/internal/known-issues.md @@ -8,20 +8,9 @@ Ordered by severity. See [`docs/roadmap.md`](../roadmap.md) for the narrative ve which also covers deliberate non-goals. -**3 open:** 1 high, 1 medium, 1 low. +**3 open:** 1 medium, 2 low. -## 1. GPL v3 is asserted over the Python logo and Python Powered badges, which are PSF trademarks - -**Severity:** High -**Where:** `LICENSE.md`, `README.md` (qualified in this pass), `python_logo_widgets/imgs/*.gif` - -**What:** `LICENSE.md` is the GNU GPL v3, and the README stated 'This project is licensed under the [GNU General Public License]' with no carve-out. The three bundled GIFs are the Python logo and the two 'Python Powered' badges -- trademarks of the Python Software Foundation, governed by the [PSF Trademark Usage Policy](https://www.python.org/psf/trademarks/). The package is published to PyPI as `Python-Logo-Widgets`, so the images are redistributed with it. The credits table names the PSF, but as a project credit rather than as a rights holder. - -**Why it matters:** The GPL grants every recipient the right to modify and redistribute what it covers -- which is precisely what a trademark policy restricts, and which the author is not in a position to grant over someone else's marks. Anyone taking the licence at face value could reasonably conclude they may alter the Python logo and ship the result, which the PSF policy does not permit. This is the one repository in the sweep whose *entire content* is third-party trademarked artwork, so the mismatch is not a corner case -- it is the whole package. - -**Suggested fix:** Owner's decision, not a documentation change. Options: state the split explicitly in `LICENSE.md` (code GPL v3, images PSF trademarks under the PSF policy, redistributed under the nominative use the badges are intended for); add a `NOTICE` or `CONTENT_LICENSE.md` recording the PSF's terms; or replace the bundled marks with the author's own artwork and reference the official badges by URL. The README is qualified in this pass; the licence file itself is untouched. - -## 2. The privacy policy and terms describe a service this package is not +## 1. The privacy policy and terms describe a service this package is not **Severity:** Medium **Where:** `docs/legal/PRIVACY.md`, `docs/legal/TERMS.md` @@ -32,6 +21,17 @@ which also covers deliberate non-goals. **Suggested fix:** Delete both, or replace them with two sentences: this package collects no data, makes no network requests, and writes nothing to disk. If terms are wanted for the PyPI listing, they should describe a library rather than a Service with Accounts. +## 2. The GPL licence file does not mention the PSF marks it ships alongside + +**Severity:** Low +**Where:** `LICENSE.md`, `README.md` (warning added in this pass), `python_logo_widgets/imgs/*.gif` + +**What:** `LICENSE.md` is the GNU GPL v3 with no carve-out, and the three bundled GIFs are the Python logo and the two 'Python Powered' badges -- copyright and trademarks of the Python Software Foundation, governed by the [PSF Trademark Usage Policy](https://www.python.org/psf/trademarks/). The package is published to PyPI, so the images are redistributed with it. Read alone, the licence file implies the GPL's modify-and-redistribute permission extends to the marks; it does not. + +**Why it matters:** **Resolved -- the owner has decided the licence stays as it is, with a warning added instead.** The remaining exposure is that `LICENSE.md` is the file a redistributor reads first and it still says nothing about the marks, so the correction lives only in the README and these docs. That is a documentation-shaped mitigation for a licence-shaped ambiguity, which is why this stays on the list rather than being closed outright. + +**Suggested fix:** Done in this pass: the README carries a prominent warning that the images are PSF property and not covered by the GPL, repeated in the documentation index and the FAQ. If it ever becomes worth strengthening, a short `NOTICE` file beside `LICENSE.md` -- naming the marks, the PSF, and the trademark policy -- would put the same statement where a redistributor actually looks, without altering the licence itself. + ## 3. str(files(...)) assumes a filesystem path, so the package breaks when zipped **Severity:** Low diff --git a/docs/roadmap.md b/docs/roadmap.md index a0b750f..34381d0 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -8,12 +8,14 @@ Direction, not a schedule. Defects are in Three embeddable widgets, images bundled and resolved correctly, references held properly, the original function API preserved, and tests for both. It does what it says. -## Considered +## Settled + +**The licence position on the images.** The repository stays GPL v3 for the code, with the Python +logo and "Python Powered" badges carrying the PSF's own copyright and trademark terms. That split +is now stated in the README, the documentation index, and the FAQ rather than left to be inferred +from a licence file that does not mention the marks. -**Settling the licence position on the images.** The most important item, and it is a decision -rather than a code change: the repository is GPL v3, and the logo and badges are PSF trademarks -that cannot be relicensed that way. Stating the split explicitly — code GPL, marks PSF — is the -minimum; the README now does, and the repository's own licensing should follow. +## Considered **Replacing the boilerplate legal documents.** A privacy policy describing account creation and personal data collection, for a package that opens no connection, is worse than none — it implies