# Traitlets

[![Tests](https://github.com/ipython/traitlets/actions/workflows/tests.yml/badge.svg)](https://github.com/ipython/traitlets/actions/workflows/tests.yml)
[![Documentation Status](https://readthedocs.org/projects/traitlets/badge/?version=latest)](https://traitlets.readthedocs.io/en/latest/?badge=latest)
[![Tidelift](https://tidelift.com/subscription/pkg/pypi-traitlets)](https://tidelift.com/badges/package/pypi/traitlets)

|               |                                      |
| ------------- | ------------------------------------ |
| **home**      | https://github.com/ipython/traitlets |
| **pypi-repo** | https://pypi.org/project/traitlets/  |
| **docs**      | https://traitlets.readthedocs.io/    |
| **license**   | Modified BSD License                 |

Traitlets is a pure Python library enabling:

- the enforcement of strong typing for attributes of Python objects
  (typed attributes are called _"traits"_);
- dynamically calculated default values;
- automatic validation and coercion of trait attributes when attempting a
  change;
- registering for receiving notifications when trait values change;
- reading configuring values from files or from command line
  arguments - a distinct layer on top of traitlets, so you may use
  traitlets without the configuration machinery.

Its implementation relies on the [descriptor](https://docs.python.org/howto/descriptor.html)
pattern, and it is a lightweight pure-python alternative of the
[_traits_ library](https://docs.enthought.com/traits/).

Traitlets powers the configuration system of IPython and Jupyter
and the declarative API of IPython interactive widgets.

## Installation

For a local installation, make sure you have
[pip installed](https://pip.pypa.io/en/stable/installing/) and run:

```bash
pip install traitlets
```

For a **development installation**, clone this repository, change into the
`traitlets` root directory, and run pip:

```bash
git clone https://github.com/ipython/traitlets.git
cd traitlets
pip install -e .
```

## Running the tests

```bash
pip install "traitlets[test]"
py.test traitlets
```

## Code Styling

`traitlets` has adopted automatic code formatting so you shouldn't
need to worry too much about your code style.
As long as your code is valid,
the pre-commit hook should take care of how it should look.

To install `pre-commit` locally, run the following::

```
pip install pre-commit
pre-commit install
```

You can invoke the pre-commit hook by hand at any time with::

```
pre-commit run
```

which should run any autoformatting on your code
and tell you about any errors it couldn't fix automatically.
You may also install [black integration](https://github.com/psf/black#editor-integration)
into your text editor to format code automatically.

If you have already committed files before setting up the pre-commit
hook with `pre-commit install`, you can fix everything up using
`pre-commit run --all-files`. You need to make the fixing commit
yourself after that.

Some of the hooks only run on CI by default, but you can invoke them by
running with the `--hook-stage manual` argument.

## Usage

Any class with trait attributes must inherit from `HasTraits`.
For the list of available trait types and their properties, see the
[Trait Types](https://traitlets.readthedocs.io/en/latest/trait_types.html)
section of the documentation.

### Dynamic default values

To calculate a default value dynamically, decorate a method of your class with
`@default({traitname})`. This method will be called on the instance, and
should return the default value. In this example, the `_username_default`
method is decorated with `@default('username')`:

```Python
import getpass
from traitlets import HasTraits, Unicode, default

class Identity(HasTraits):
    username = Unicode()

    @default('username')
    def _username_default(self):
        return getpass.getuser()
```

### Callbacks when a trait attribute changes

When a trait changes, an application can follow this trait change with
additional actions.

To do something when a trait attribute is changed, decorate a method with
[`traitlets.observe()`](https://traitlets.readthedocs.io/en/latest/api.html?highlight=observe#traitlets.observe).
The method will be called with a single argument, a dictionary which contains
an owner, new value, old value, name of the changed trait, and the event type.

In this example, the `_num_changed` method is decorated with `` @observe(`num`) ``:

```Python
from traitlets import HasTraits, Integer, observe

class TraitletsExample(HasTraits):
    num = Integer(5, help="a number").tag(config=True)

    @observe('num')
    def _num_changed(self, change):
        print("{name} changed from {old} to {new}".format(**change))
```

and is passed the following dictionary when called:

```Python
{
  'owner': object,  # The HasTraits instance
  'new': 6,         # The new value
  'old': 5,         # The old value
  'name': "foo",    # The name of the changed trait
  'type': 'change', # The event type of the notification, usually 'change'
}
```

### Validation and coercion

Each trait type (`Int`, `Unicode`, `Dict` etc.) may have its own validation or
coercion logic. In addition, we can register custom cross-validators
that may depend on the state of other attributes. For example:

```Python
from traitlets import HasTraits, TraitError, Int, Bool, validate

class Parity(HasTraits):
    value = Int()
    parity = Int()

    @validate('value')
    def _valid_value(self, proposal):
        if proposal['value'] % 2 != self.parity:
            raise TraitError('value and parity should be consistent')
        return proposal['value']

    @validate('parity')
    def _valid_parity(self, proposal):
        parity = proposal['value']
        if parity not in [0, 1]:
            raise TraitError('parity should be 0 or 1')
        if self.value % 2 != parity:
            raise TraitError('value and parity should be consistent')
        return proposal['value']

parity_check = Parity(value=2)

# Changing required parity and value together while holding cross validation
with parity_check.hold_trait_notifications():
    parity_check.value = 1
    parity_check.parity = 1
```

However, we **recommend** that custom cross-validators don't modify the state
of the HasTraits instance.

## About the IPython Development Team

The IPython Development Team is the set of all contributors to the IPython project.
This includes all of the IPython subprojects.

The core team that coordinates development on GitHub can be found here:
https://github.com/jupyter/.

## Our Copyright Policy

IPython uses a shared copyright model. Each contributor maintains copyright
over their contributions to IPython. But, it is important to note that these
contributions are typically only changes to the repositories. Thus, the IPython
source code, in its entirety is not the copyright of any single person or
institution. Instead, it is the collective copyright of the entire IPython
Development Team. If individual contributors want to maintain a record of what
changes/contributions they have specific copyright on, they should indicate
their copyright in the commit message of the change, when they commit the
change to one of the IPython repositories.

With this in mind, the following banner should be used in any source code file
to indicate the copyright and license terms:

```
# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
```


# devilry

## Develop

Requires:

- https://github.com/pyenv/pyenv
- Docker (Docker desktop or similar)

### Use conventional commits for GIT commit messages

See https://www.conventionalcommits.org/en/v1.0.0/.
You can use this git commit message format in many different ways, but the easiest is:

- Use commitizen: https://commitizen-tools.github.io/commitizen/commit/
- Use an editor extension, like https://marketplace.visualstudio.com/items?itemName=vivaxy.vscode-conventional-commits for VScode.
- Just learn to write the format by hand (can be error prone to begin with, but it is fairly easy to learn).

### Install hatch and commitizen

NOTE: You only need hatch if you need to build releases, and you
only need commitizen for releases OR to make it easy to follow
conventional commits for your commit messages
(see _Use conventional commits for GIT commit messages_ above).

First install pipx with:

```bash
brew install pipx
pipx ensurepath
```

Then install hatch and commitizen:

```bash
pipx install hatch
pipx install commitizen
```

See https://github.com/pypa/pipx, https://hatch.pypa.io/latest/install/
and https://commitizen-tools.github.io/commitizen/ for more install alternatives if
needed, but we really recommend using pipx since that is isolated.

### Install development dependencies

#### Install a local python version with pyenv:

```bash
pyenv install 3.10
pyenv local 3.10
```

#### Install dependencies in a virtualenv:

```bash
./recreate-virtualenv.sh
```

Alternatively, create virtualenv manually (this does the same as recreate-virtualenv.sh):

```bash
python -m venv .venv
```

the ./recreate-virtualenv.sh script is just here to make creating virtualenvs more uniform
across different repos because some repos will require extra setup in the virtualenv
for package authentication etc.

#### Install dependencies in a virtualenv:

```bash
source .venv/bin/activate   # enable virtualenv
.venv/bin/pip install -e ".[dev,test]"
```

### Upgrade your local packages

This will upgrade all local packages according to the constraints
set in pyproject.toml:

```bash
.venv/bin/pip install --upgrade --upgrade-strategy=eager ".[dev,test]"
```

### Run postgres and redis

```bash
docker compose up
```

### Run dev server

```bash
source .venv/bin/activate   # enable virtualenv
ievv devrun
```

### Create or re-create a devdatabase
You should always clear the database before recreating it. The easiest way is just to clear the docker resources (and volumes) and start it again.
```bash
docker compose down -v
docker compose up
```

Run dev server (in a new terminal)
```bash
source .venv/bin/activate   # activate virtualenv
ievv devrun
```

Load devdatabase SQL-file (in a new terminal)
```bash
source .venv/bin/activate   # activate virtualenv
docker compose exec -T postgres psql -U dbdev --dbname=dbdev -p 5432 -h localhost < devilry/project/develop/dumps/default.sql
python manage.py migrate
ievv customsql -i -r
```

If the dump should be updated for e.g new migrations, run the following and commit to repo:
```bash
docker compose exec -T postgres pg_dump --clean --no-owner --no-acl --no-privileges -U dbdev -h localhost -p 5432 dbdev > devilry/project/develop/dumps/default.sql
```

### Test users in the devdatabase
All users have ``test`` as their password, and the most commonly needed users are:

- Superuser: grandma@example.com
- Admin (and examiner): odin@example.com
- Examiner (and student): thor@example.com
- Student: april@example.com

You can find them all by logging in as grandma@example.com and going to http://localhost.test:8000/djangoadmin/devilry_account/user/

### Browse uploaded files
Files are stored in MinIO (S3 compatible storage that is run via docker-compose).
To browse files:

- Go to http://localhost:9001/
- Login with:
  - username: ``testuser``
  - password: ``testpassword``
- Select _Object browser_ in the sidebar.

The MinIO files is stored on disk in the ``minio_devdata`` directory in the root
of the repo, and you can stop docker compose, and just run ``rm -rf minio_devdata``
to remove all the files.

### Run tests

```bash
source .venv/bin/activate   # enable virtualenv
pytest devilry
```

### Build css/javascript:
```bash
source .venv/bin/activate   # activate virtualenv
nvm use 14    # May need to run "nvm install 14" first
ievv buildstatic
# ... or if you want to watch for changes ...:
ievv buildstatic --watch
```

To remove and reinstall all node-packages:
```bash
source .venv/bin/activate   # activate virtualenv
nvm use 14    # May need to run "nvm install 14" first
ievv buildstatic --npm-clean-node-modules
```

### Destroy postgres and redis

```bash
docker compose down -v
```

## Documentation

https://devilry.readthedocs.io

## Release

### Translations

To translate new texts, do the following:

- ``ievv makemessages``
- Translate the .po files. Poedit is a great tool for this.
- ``ievv compilemessages``
- Commit the changes

### Set version and build staticfiles

First make sure you have NO UNCOMITTED CHANGES!

Release (create changelog, increment version, build staticfiles, commit and tag the change) with:

```bash
nvm use 14
tools/release/prepare-release.py prepare --apply  # This will bump the version and then build and commit staticfiles.
git push && git push --tags
```

### NOTE (release):

- `cz bump` automatically updates CHANGELOG.md, updates version file(s), commits the change and tags the release commit.
- If you are unsure about what `cz bump` will do, run it with `--dry-run`. You can use
  options to force a specific version instead of the one it automatically selects
  from the git log if needed, BUT if this is needed, it is a sign that someone has messed
  up with their conventional commits.
- `cz bump` only works if conventional commits (see section about that above) is used.
- `cz bump` can take a specific version etc, but it automatically select the correct version
  if conventional commits has been used correctly. See https://commitizen-tools.github.io/commitizen/.
- If you need to add more to CHANGELOG.md (migration guide, etc), you can just edit
  CHANGELOG.md after the release, and commit the change with a `docs: some useful message`
  commit.
- The `cz` command comes from `commitizen` (install documented above).

### What if the release fails?

See _How to revert a bump_ in the [commitizen FAQ](https://commitizen-tools.github.io/commitizen/faq/#how-to-revert-a-bump).

### Migrationguide and changelog (for official readthedocs)
- Add a migration guide to not_for_deploy/docs/sysadmin/migrationguides/
- Add a changelog to not_for_deploy/docs/user/changelog/

### Release to pypi:

```bash
hatch build -t sdist
hatch publish
rm dist/*              # optional cleanup
```


[![PyPI Status](https://img.shields.io/pypi/v/hcipy.svg?logo=pypi&logoColor=white)](https://pypi.org/project/hcipy/)
[![Conda Status](https://img.shields.io/conda/vn/conda-forge/hcipy?logo=anaconda&logoColor=white)](https://anaconda.org/conda-forge/hcipy)
[![Build Status](https://img.shields.io/azure-devops/build/ehpor/hcipy/1/master?logo=azure-pipelines)](https://dev.azure.com/ehpor/hcipy/_build?definitionId=1)
[![Coverage Status](https://img.shields.io/codecov/c/gh/ehpor/hcipy?logo=codecov&logoColor=white)](https://codecov.io/gh/ehpor/hcipy)
[![Documentation Status](https://img.shields.io/badge/docs-latest%20build-brightgreen?logo=read-the-docs&logoColor=white)](https://docs.hcipy.org/dev)
[![License](https://img.shields.io/github/license/ehpor/hcipy.svg?logo=open-source-initiative&logoColor=white)](https://opensource.org/licenses/MIT)

# HCIPy: High Contrast Imaging for Python

![HCIPy banner](https://github.com/ehpor/hcipy/raw/master/doc/hcipy_banner.png "HCIPy banner")

HCIPy is an open-source object-oriented framework written in Python for performing end-to-end simulations of high-contrast imaging instruments for astronomy.

The library defines wavefronts and optical elements for defining an optical system, and provides both Fraunhofer and Fresnel diffraction propgators. Polarization is supported using Jones calculus, with polarizers and waveplates included out of the box. It implements atmospheric turbulence using thin infinitely-long phase screens, and can model scintillation using Fresnel propagation between individual layers. Many wavefront sensors are implemented including a Shack-Hartmann and Pyramid wavefront sensor. Implemented coronagraphs include the vortex, Lyot and APP coronagraph.

By including simulation of both adaptive optics and coronagraphy into a single framework, HCIPy allows simulations including feedback from post-coronagraphic focal-plane wavefront sensors to the AO system.

The main website is hosted at <https://hcipy.org>. For documentation, see <https://docs.hcipy.org>.

## Team

HCIPy was originally developed by a small team of astronomers at Leiden Observatory, but has since received external constributions from scientists and software developers around the world. For a current list, please visit our [website](https://hcipy.org/team.html).

## Citing

If you use HCIPy for your own research, we ask you to cite the HCIPy proceeding ([Por et al. 2018](https://doi.org/10.1117/12.2314407)). If there is no appropriate place in the body text to cite the proceeding, please include something along the lines of the following in your acknowledgements:

> This research made use of HCIPy, an open-source object-oriented framework written in Python for performing end-to-end simulations of high-contrast imaging instruments ([Por et al. 2018](https://doi.org/10.1117/12.2314407)).

## Contributions

If you have something to add, or want something added to HCIPy, please let us know using a Github issue. We actively support external contributions to HCIPy, small and large. Please look at the [contributing guide](https://docs.hcipy.org/dev/development/contributing_guide.html) for more information.


![IBM Security](https://raw.githubusercontent.com/ibmresilient/resilient-python-api/master/resilient-sdk/assets/IBM_Security_lockup_pos_RGB.png)

# IBM SOAR Python APIs

This directory contains the source code for:

 * [resilient](./resilient), a Python client module for the IBM SOAR REST API.
 * [resilient-circuits](./resilient-circuits), an application framework used to run IBM SOAR Apps and Integrations.
 * [resilient-lib](./resilient-lib), a package with common library calls which facilitate the development of Apps for IBM SOAR.
* [resilient-sdk](./resilient-sdk), a CLI tool needed to develop IBM SOAR Apps.

See more details of usage and examples for these packages at our [docs](https://ibm.biz/soar-python-docs).

## Documentation
The IBM SOAR App Developer's Guide provides information on using the IBM SOAR Resilient Circuits Framework to run Apps and Integrations. The guide is available on the IBM Knowledge Center at [ibm.biz/soar-docs](https://ibm.biz/soar-docs). On this web page, select your IBM SOAR platform version. On the following page, you can find the App Developer's Guide by expanding **Apps** in the Table of Contents pane.

For our API Documentation on these libraries, please see [ibm.biz/soar-python-docs](https://ibm.biz/soar-python-docs).

# Contributing

Please report issues using the [Issues](https://github.com/ibmresilient/resilient-python-api/issues) tab on GitHub.

Contributions are welcome.  Please read the [CONTRIBUTING](CONTRIBUTING.md) guidelines for more about the process.

# Open Source @ IBM

[Find more open source projects on the IBM Github Page](http://ibm.github.io/)


# Python Implementation of the Ethereum protocol

[![Join the conversation on Discord](https://img.shields.io/discord/809793915578089484?color=blue&label=chat&logo=discord&logoColor=white)](https://discord.gg/GHryRvPB84)
[![Build Status](https://circleci.com/gh/ethereum/py-evm.svg?style=shield)](https://circleci.com/gh/ethereum/py-evm)
[![PyPI version](https://badge.fury.io/py/py-evm.svg)](https://badge.fury.io/py/py-evm)
[![Python versions](https://img.shields.io/pypi/pyversions/py-evm.svg)](https://pypi.python.org/pypi/py-evm)
[![Docs build](https://readthedocs.org/projects/py-evm/badge/?version=latest)](https://py-evm.readthedocs.io/en/latest/?badge=latest)

## Py-EVM

Py-EVM is an implementation of the Ethereum protocol in Python. It contains the low level
primitives for the original proof-of-work (POW), (formerly known as Ethereum 1.0) chain
as well as emerging support for the proof-of-stake (POS) (formerly known as Ethereum 2.0) spec.

### Goals

Py-EVM aims to eventually become the defacto Python implementation of the Ethereum protocol,
enabling a wide array of use cases for both public and private chains.

In particular Py-EVM aims to:

- be a reference implementation of the Ethereum POW and POS implementations in one of the most widely used and understood languages, Python.

- be easy to understand and modifiable

- have clear and simple APIs

- come with solid, friendly documentation

- deliver the low level primitives to build various clients on top (including *full* and *light* clients)

- be highly flexible to support both research as well as alternate use cases like private chains.

## Quickstart

```sh
python -m pip install py-evm
```

[Get started in 5 minutes](https://py-evm.readthedocs.io/en/latest/guides/building_an_app_that_uses_pyevm.html)

## Documentation

Check out the [documentation on our official website](https://py-evm.readthedocs.io/en/latest/)

## Developer Setup

If you would like to hack on py-evm, please check out the [Snake Charmers
Tactical Manual](https://github.com/ethereum/snake-charmers-tactical-manual)
for information on how we do:

- Testing
- Pull Requests
- Documentation

We use [pre-commit](https://pre-commit.com/) to maintain consistent code style. Once
installed, it will run automatically with every commit. You can also run it manually
with `make lint`. If you need to make a commit that skips the `pre-commit` checks, you
can do so with `git commit --no-verify`.

### Development Environment Setup

```sh
git clone git@github.com:ethereum/py-evm.git
cd py-evm
virtualenv -p python3 venv
. venv/bin/activate
python -m pip install -e ".[dev]"
pre-commit install
```

### Release setup

To release a new version:

```sh
make release bump=$$VERSION_PART_TO_BUMP$$
```

To issue the next version in line, specify which part to bump,
like `make release bump=minor` or `make release bump=devnum`. This is typically done from the
main branch, except when releasing a beta (in which case the beta is released from main,
and the previous stable branch is released from said branch).

## Want to help?

Want to file a bug, contribute some code, or improve documentation? Excellent! Read up on our
guidelines for [contributing](https://py-evm.readthedocs.io/en/latest/contributing.html) and then check out one of our issues that are labeled [Good First Issue](https://github.com/ethereum/py-evm/issues?q=is%3Aissue+is%3Aopen+label%3A%22Good+First+Issue%22).


[![Downloads](https://pepy.tech/badge/qt-py)](https://pepy.tech/project/qt-py)
[![Run Tests](https://github.com/mottosso/Qt.py/actions/workflows/run-tests.yml/badge.svg)](https://github.com/mottosso/Qt.py/actions)
[![PyPI version](https://badge.fury.io/py/Qt.py.svg)](https://pypi.python.org/pypi/Qt.py)
[![Anaconda-Server Badge](https://anaconda.org/conda-forge/qt.py/badges/version.svg)](https://anaconda.org/conda-forge/qt.py)
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Qt-py/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Reviewed by Hound](https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg)](https://houndci.com)

Qt.py enables you to write software that runs on any of the 4 supported bindings - PySide2, PyQt5, PySide and PyQt4.

##### News

| Date     | Version   | Event
|:---------|:----------|:----------
| May 2024 | [1.4.1][] | Added support for Qt 6
| Jan 2024 | [1.3.9][] | Run CI on Github Actions, instead of Travis CI.
| Sep 2020 | [1.3.0][] | Stability improvements and greater ability for `QtCompat.wrapInstance` to do its job
| Jun 2019 | [1.2.1][] | Bugfixes and [additional members](https://github.com/mottosso/Qt.py/releases/tag/1.2.0)
| Jan 2018 | [1.1.0][] | Adds new test suite, new members
| Mar 2017 | [1.0.0][] | Increased safety, **backwards incompatible**
| Sep 2016 | [0.6.9][] | Stable release
| Sep 2016 | [0.5.0][] | Alpha release of `--convert`
| Jun 2016 | [0.2.6][] | First release of Qt.py

- [More details](https://github.com/mottosso/Qt.py/releases).

[0.2.6]: https://github.com/mottosso/Qt.py/releases/tag/0.2.6
[0.5.0]: https://github.com/mottosso/Qt.py/releases/tag/0.5.0
[0.6.9]: https://github.com/mottosso/Qt.py/releases/tag/0.6.9
[1.0.0]: https://github.com/mottosso/Qt.py/releases/tag/1.0.0
[1.1.0]: https://github.com/mottosso/Qt.py/releases/tag/1.1.0
[1.2.1]: https://github.com/mottosso/Qt.py/releases/tag/1.2.1
[1.3.0]: https://github.com/mottosso/Qt.py/releases/tag/1.3.0
[1.3.9]: https://github.com/mottosso/Qt.py/releases/tag/1.3.9
[1.4.0]: https://github.com/mottosso/Qt.py/releases/tag/1.4.1

##### Guides

- [Qt 6 Transition Guide](#qt-6-transition-guide)
- [Developing with Qt.py](https://fredrikaverpil.github.io/blog/2016/07/25/developing-with-qtpy/)
- [Dealing with Maya 2017 and PySide2](https://fredrikaverpil.github.io/blog/2016/07/25/dealing-with-maya-2017-and-pyside2/)
- [Vendoring Qt.py](https://fredrikaverpil.github.io/blog/2017/05/04/vendoring-qtpy/)
- [Udemy Course](https://www.udemy.com/python-for-maya/learn/v4/t/lecture/6027394)
- [PythonBytes #77](https://pythonbytes.fm/episodes/show/77/you-don-t-have-to-be-a-workaholic-to-win) (Starts at 5:00)

##### Table of contents

- [Project goals](#project-goals)
- [Install](#install)
- [Usage](#usage)
- [Documentation](#documentation)
  - [Environment Variables](#environment-variables)
  - [Subset](#subset)
  - [Branch binding-specific code](#branch-binding-specific-code)
  - [Override preferred choice](#override-preferred-choice)
  - [QtSiteConfig.py](#qtsiteconfigpy)
  - [Compile Qt Designer files](#compile-qt-designer-files)
  - [Loading Qt Designer files](#loading-qt-designer-files)
  - [sip API v2](#sip-api-v2)
- [Rules](#rules)
- [How it works](#how-it-works)
- [Known problems](#known-problems)
- [Who's using Qt.py?](#whos-using-qtpy)
- [Projects using Qt.py](#projects-using-qtpy)
- [Projects similar to Qt.py](#projects-similar-to-qtpy)
- [Developer guide](#developer-guide)
- [Qt 6 transition guide](#qt-6-transition-guide)

### Project goals

Write once, run in any binding.

Qt.py was born in the film and visual effects industry to address the growing need for software capable of running with more than one flavor of the Qt bindings for Python - PySide, PySide2, PyQt4 and PyQt5.

| Goal                                 | Description
|:-------------------------------------|:---------------
| *Support co-existence*               | Qt.py should not affect other bindings running in same interpreter session.
| *Build for one, run with all*        | Code written with Qt.py should run on any binding.
| *Explicit is better than implicit*   | Differences between bindings should be visible to you.

See [`CONTRIBUTING.md`](CONTRIBUTING.md) for more details.

### Install

Qt.py is a single file and can either be [copy/pasted](https://raw.githubusercontent.com/mottosso/Qt.py/master/Qt.py) into your project, [downloaded](https://github.com/mottosso/Qt.py/archive/master.zip) as-is, cloned as-is or installed via `pip` or `conda`.

```bash
# From PyPI
$ pip install Qt.py
```

```bash
# From Anaconda
$ conda config --add channels conda-forge
$ conda install qt.py
```

- Pro tip: **Never use the latest commit for production**. Instead, use [the latest release](https://github.com/mottosso/Qt.py/releases). That way, when you read bug reports or make one for yourself you will be able to match a version with the problem without which you will not know which fixes apply to you nor would we be able to help you. Installing via pip or conda as above ensures you are provided the latest *stable* release. Unstable releases are suffixed with a `.b`, e.g. `1.1.0.b3`.
- Pro tip: Supports [vendoring](https://fredrikaverpil.github.io/blog/2017/05/04/vendoring-qtpy/)

### Usage

Use Qt.py as you would use PySide2.

![image](https://cloud.githubusercontent.com/assets/2152766/15653248/b5ce298e-2683-11e6-8c0c-f041ecae203d.png)

```python
import sys
from Qt import QtWidgets

app = QtWidgets.QApplication(sys.argv)
button = QtWidgets.QPushButton("Hello World")
button.show()
app.exec_()
```

- Also see [/examples](examples)

### Documentation

All members of `Qt` stem directly from those available via PySide2, along with these additional members.

| Attribute               | Returns     | Description
|:------------------------|:------------|:------------
| `__version__`           | `str`       | Version of this project
| `__binding__`           | `str`       | A string reference to binding currently in use
| `__qt_version__`        | `str`       | Reference to version of Qt, such as Qt 5.6.1
| `__binding_version__`   | `str`       | Reference to version of binding, such as PySide 1.2.6

**Example**

```python
>>> from Qt import __binding__
>>> __binding__
'PyQt5'
```

### Compatibility

Qt.py also provides compatibility wrappers for critical functionality that differs across bindings, these can be found in the added `QtCompat` submodule.

| Attribute                                 | Returns     | Description
|:------------------------------------------|:------------|:------------
| `loadUi(uifile=str, baseinstance=QWidget)`| `QObject`   | Minimal wrapper of PyQt4.loadUi and PySide equivalent
| `translate(...)`        					| `function`  | Compatibility wrapper around [QCoreApplication.translate][]
| `wrapInstance(addr=long, type=QObject)`   | `QObject`   | Wrapper around `shiboken2.wrapInstance` and PyQt equivalent
| `getCppPointer(object=QObject)`           | `long`      | Wrapper around `shiboken2.getCppPointer` and PyQt equivalent
| `isValid(object=QObject)`                 | `bool`      | Wrapper around `shiboken2.isValid` and PyQt equivalent
| `dataChanged(topLeft=QModelIndex, bottomRight=QModelIndex, roles=[])` | `None` | Wrapper around `QtCore.QAbstractItemModel.dataChanged.emit`

[QCoreApplication.translate]: https://doc.qt.io/qt-5/qcoreapplication.html#translate

**Example**

```python
>>> from Qt import QtCompat
>>> QtCompat.loadUi
```

#### Class specific compatibility objects

Between Qt4 and Qt5 there have been many classes and class members that are obsolete. Under Qt.QtCompat there are many classes with names matching the classes they provide compatibility functions. These will match the PySide2 naming convention.

```python
from Qt import QtCore, QtWidgets, QtCompat
header = QtWidgets.QHeaderView(QtCore.Qt.Horizontal)
QtCompat.QHeaderView.setSectionsMovable(header, False)
movable = QtCompat.QHeaderView.sectionsMovable(header)
```

This also covers inconsistencies between bindings. For example PyQt4's QFileDialog matches Qt4's return value of the selected. While all other bindings return the selected filename and the file filter the user used to select the file. `Qt.QtCompat.QFileDialog` ensures that getOpenFileName(s) and getSaveFileName always return the tuple.

##### Environment Variables

These are the publicly facing environment variables that in one way or another affect the way Qt.py is run.

| Variable                  | Type  | Description
|:--------------------------|:------|:----------
| QT_PREFERRED_BINDING_JSON | str   | Override order and content of binding to try. This can apply per Qt.py namespace.
| QT_PREFERRED_BINDING      | str   | Override order and content of binding to try. Used if QT_PREFERRED_BINDING_JSON does not apply.
| QT_VERBOSE                | bool  | Be a little more chatty about what's going on with Qt.py
| QT_SIP_API_HINT           | int   | Sets the preferred SIP api version that will be attempted to set.

##### Subset (or "common members")

Members of Qt.py is a subset of PySide2. Which means for a member to be made accessible via Qt.py, it will need to (1) be accessible via PySide2 and (2) each of the other supported bindings. This excludes large portions of the Qt framework, including the newly added QtQml and QtQuick modules but guarantees that anything you develop with Qt.py will work identically on any binding - PySide, PySide2, PyQt4 and PyQt5. If you need to use such excluded modules with Qt.py, please see [QtSiteConfig.py](#qtsiteconfigpy).

We call this subset "common members" and these can be generated by running the `build_membership.sh` script. The script will output all modules and members of each binding into individual JSON files. These JSON files are then compared and a `common_members.json` file is generated. The contents of this file is copy-pasted into the `_common_members` dictionary of Qt.py. Please note that the script will only use the very latest version of our [Docker test suite](DOCKER.md) to generate the common members subset, using the most up-to-date set of VFX Platform-stipulated software versions.

:warning: The version of PySide2 used as reference is the one specified on [VFX Platform](http://www.vfxplatform.com/), currently version is 2.0.x. But unfortunately, the version string of PySide2 is not yet properly maintained and the VFX Platform does not specifiy a explicit commit SHA for PySide2. Therefore, it could be difficult to know exactly which PySide2 is running on your system (unless you built it from source). In layman's terms; as PySide2 is in development and is continuously adding new support for modules, you may see differences between PySide2 built early in the year vs PySide2 built later in the year. The exact commit SHAs of PySide2 used by the Qt.py test suite can be reviewed in [DOCKER.md](DOCKER.md). QtC implemented an alternative way to identify which version of PySide2 you are running. You can read more about that [here](https://codereview.qt-project.org/#/c/202199/).

##### Branch binding-specific code

Some bindings offer features not available in others, you can use `__binding__` to capture those.

```python
if "PySide" in __binding__:
  do_pyside_stuff()
```

##### Override preferred choice

If your system has multiple choices where one or more is preferred, you can override the preference and order in which they are tried with this environment variable.

```bash
$ set QT_PREFERRED_BINDING=PyQt5  # Windows
$ export QT_PREFERRED_BINDING=PyQt5  # Unix/OSX
$ python -c "import Qt;print(Qt.__binding__)"
PyQt5
```

Constrain available choices and order of discovery by supplying multiple values.

```bash
# Try PyQt4 first and then PySide, but nothing else.
$ export QT_PREFERRED_BINDING=PyQt4:PySide
```

Using the OS path separator (`os.pathsep`) which is `:` on Unix systems and `;` on Windows.

If you need to control the preferred choice of a specific vendored Qt.py you can use the `QT_PREFERRED_BINDING_JSON` environment variable instead.

```json
{
    "Qt":["PyQt5"],
    "myproject.vendor.Qt":["PyQt5"],
    "default":["PySide2"]
}
```

This json data forces any code that uses `import Qt` or `import myproject.vendor.Qt` to use PyQt5(`from x import Qt` etc works too, this is based on `__name__` of the Qt.py being imported). Any other imports of a Qt module will use the "default" PySide2 only. If `"default"` is not provided or a Qt.py being used does not support `QT_PREFERRED_BINDING_JSON`, `QT_PREFERRED_BINDING` will be respected.

```bash
# Try PyQt5 first and then PyQt4 for the Qt module name space.
$ export QT_PREFERRED_BINDING_JSON="{"Qt":["PyQt5","PyQt4"]}"
# Use PyQt4 for any other Qt module name spaces.
$ export QT_PREFERRED_BINDING=PySide2
```

##### QtSiteConfig.py

Add or remove members from Qt.py at run-time.

-  [Examples](/examples/QtSiteConfig)

If you need to expose a module that isn't included in Qt.py by default or wish to remove something from being exposed in Qt.py you can do so by creating a `QtSiteConfig.py` module and making it available to Python.

1. Create a new file `QtSiteConfig.py`
2. Implement `update_members`
3. Expose to Python

```python
# QtSiteConfig.py
def update_members(members):
    """Called by Qt.py at run-time to modify the modules it makes available.

    Arguments:
        members (dict): The members considered by Qt.py
    """
    members.pop("QtCore")
```

Finally, expose the module to Python.

```bash
$ set PYTHONPATH=/path/to
$ python -c "import Qt.QtCore"
ImportError: No module named Qt.QtCore
```

> Linux and MacOS users, replace `set` with `export`

##### Compile Qt Designer files

> WARNING - ALPHA FUNCTIONALITY

> See [#132](https://github.com/mottosso/Qt.py/pull/132) for details.

`.ui` files compiled via `pyside2-uic` inherently contain traces of PySide2 - e.g. the line `from PySide2 import QtGui`.

In order to use these with Qt.py, or any other binding, one must first erase such traces and replace them with cross-compatible code.

```bash
$ pyside2-uic my_ui.ui -o my_ui.py
$ python -m Qt --convert my_ui.py
# Creating "my_ui_backup.py"..
# Successfully converted "my_ui.py"
```

Now you may use the file as you normally would, with Qt.py

##### Loading Qt Designer files

The `uic.loadUi` function of PyQt4 and PyQt5 as well as the `QtUiTools.QUiLoader().load` function of PySide/PySide2 are mapped to a convenience function `loadUi`.

```python
import sys
from Qt import QtCompat

app = QtWidgets.QApplication(sys.argv)
ui = QtCompat.loadUi(uifile="my.ui")
ui.show()
app.exec_()
```
For `PyQt` bindings it uses their native implementation, whereas for `PySide` bindings it uses our custom implementation borrowed from the [qtpy](https://github.com/spyder-ide/qtpy) project.

`loadUi` has two arguments as opposed to the multiple that PyQt ships with. See [here](https://github.com/mottosso/Qt.py/pull/81) for details - in a nutshell, those arguments differ between PyQt and PySide in incompatible ways.
The second argument is `baseinstance` which allows a ui to be dynamically loaded onto an existing QWidget instance.

```python
QtCompat.loadUi(uifile="my.ui", baseinstance=QtWidgets.QWidget)
```

`uifile` is the string path to the ui file to load.

If `baseinstance` is `None`, the a new instance of the top-level
widget will be created. Otherwise, the user interface is created within
the given `baseinstance`. In this case `baseinstance` must be an
instance of the top-level widget class in the UI file to load, or a
subclass thereof. In other words, if you've created a `QMainWindow`
interface in the designer, `baseinstance` must be a `QMainWindow`
or a subclass thereof, too. You cannot load a `QMainWindow` UI file
with a plain `QWidget` as `baseinstance`.

`loadUi` returns `baseinstance`, if `baseinstance` is provided.
Otherwise it will return the newly created instance of the user interface.

##### sip API v2

If you're using PyQt4, `sip` attempts to set its API to version 2 for the following:
- `QString`
- `QVariant`
- `QDate`
- `QDateTime`
- `QTextStream`
- `QTime`
- `QUrl`

### Rules

The PyQt and PySide bindings are similar, but not identical. Where there is ambiguity, there must to be a clear direction on which path to take.

**Governing API**

The official [Qt 5 documentation](http://doc.qt.io/qt-5/classes.html) is always right. Where the documentation lacks answers, PySide2 is right.

For example.

```python
# PyQt5 adheres to PySide2 signals and slots
PyQt5.Signal = PyQt5.pyqtSignal
PyQt5.Slot = PyQt5.pyqtSlot

# PySide2 adheres to the official documentation
PySide2.QtCore.QStringListModel = PySide2.QtGui.QStringListModel
```

**Caveats**

There are cases where Qt.py is not handling incompatibility issues. Please see [`CAVEATS.md`](CAVEATS.md) for more information.

### Known Problems

Send us a pull-request with known problems here!

- [Maya and incompatible bindings on PYTHONPATH](https://github.com/mottosso/Qt.py/issues/146)

### Who's using Qt.py?

Send us a pull-request with your studio here.

- [Atomic Fiction](http://www.atomicfiction.com/)
- [Bläck](http://www.blackstudios.se/)
- [Blur Studio](http://www.blur.com)
- [CGRU](http://cgru.info/)
- [Colorbleed](http://www.colorbleed.nl/)
- [Digital Domain](https://www.digitaldomain.com/)
- [Disney Animation](https://www.disneyanimation.com/)
- [Dreamworks Animation](https://github.com/dreamworksanimation)
- [Epic Games](https://www.epicgames.com/)
- [Fido](http://fido.se/)
- [Framestore](https://framestore.com)
- [ftrack](https://www.ftrack.com/)
- [Futureworks](http://futureworks.in/)
- [Industrial Brothers](http://industrialbrothers.com/)
- [Industriromantik](http://www.industriromantik.se/)
- [Mackevision](http://www.mackevision.com/)
- [Method Studios](http://www.methodstudios.com/)
- [Mikros Image](http://www.mikrosimage.com/)
- [Moonbot Studios](http://moonbotstudios.com/)
- [MPC](http://www.moving-picture.com)
- [Overmind Studios](https://www.overmind-studios.de/)
- [Psyop](http://www.psyop.com/)
- [Raynault VFX](https://www.raynault.com/)
- [Rising Sun Pictures](https://rsp.com.au)
- [Rodeo FX](https://www.rodeofx.com/en/)
- [Sony Pictures Imageworks](http://www.imageworks.com/)
- [Spin VFX](http://www.spinvfx.com/)
- [Weta Digital](https://www.wetafx.co.nz/)

Presented at Siggraph 2016, BOF!

![image](https://cloud.githubusercontent.com/assets/2152766/17621229/c2448db2-6089-11e6-915f-0604e5d8c7ee.png)

### Projects using Qt.py

Send us a pull-request with your project here.

- [USD Manager](http://www.usdmanager.org)
- [Cosmos](http://cosmos.toolsfrom.space/)
- [maya-capture-gui](https://github.com/BigRoy/maya-capture-gui)
- [pyblish-lite](https://github.com/pyblish/pyblish-lite)
- [pyvfx-boilerplate](https://github.com/fredrikaverpil/pyvfx-boilerplate)
- [riffle](https://gitlab.com/4degrees/riffle)
- [cmt](https://github.com/chadmv/cmt)
- [PythonForMayaSamples](https://github.com/dgovil/PythonForMayaSamples)
- [Kraken](https://github.com/fabric-engine/Kraken)
- [AFANASY](http://cgru.info/afanasy/afanasy)
- [Syncplay](https://github.com/Syncplay/syncplay)
- [BlenderUpdater](https://github.com/overmindstudios/BlenderUpdater)
- [QtPyConvert](https://github.com/DigitalDomain/QtPyConvert)
- [Pyper](https://gitlab.com/brunoebe/pyper.git)

### Projects similar to Qt.py

Comparison matrix.

| Project       | Audience      | Reference binding | License   | PEP8 |Standalone | PyPI   | Co-existence
|:--------------|:--------------|:------------------|:----------|------|:----------|--------|--------------
| Qt.py         | Film          | PySide2           | MIT       | X    | X         | X      | X
| [jupyter][]   | Scientific    | N/A               | N/A       | X    |           |        |
| [QtPy][]      | Scientific    | N/A               | MIT       |      | X         | X      |
| [pyqode.qt][] | Scientific    | PyQt5             | MIT       | X    |           | X      |
| [QtExt][]     | Film          | N/A               | N/A       |      | X         |        |
| [python_qt_binding][] | Robotics | N/A            | BSD       | X    | X        | X       | X

Also worth mentioning, [pyqt4topyqt5](https://github.com/rferrazz/pyqt4topyqt5); a good starting point for transitioning to Qt.py.

Send us a pull-request with your project here.

[QtPy]: https://github.com/spyder-ide/qtpy
[jupyter]: https://github.com/jupyter/qtconsole/blob/master/qtconsole/qt_loaders.py
[pyqode.qt]: https://github.com/pyQode/pyqode.qt
[QtExt]: https://bitbucket.org/ftrack/qtext
[python_qt_binding]: https://github.com/ros-visualization/python_qt_binding

### Developer Guide

Tests are performed on each aspect of the shim.

- [Functional](tests.py)
- [Caveats](build_caveats.py)
- [Examples](examples)

Each of these are run under..

- Python 2.7
- Python 3.4
- Python 3.5
- Python 3.6

..once for each binding or under a specific binding only.

Each test is run within it's own isolated process, so as to allow an `import` to occur independently from other tests. Process isolation is handled via [nosepipe](https://pypi.python.org/pypi/nosepipe).

Tests that are written at module level are run four times - once per binding - whereas tests written under a specific if-statement are run only for this particular binding.

```python
if binding("PyQt4"):
    def test_something_related_to_pyqt4():
        pass
```

**Code convention**

Below are some of the conventions that used throughout the Qt.py module and tests.

- **Etiquette: PEP8**
    - All code is written in PEP8. It is recommended you use a linter as you work, flake8 and pylinter are both good options. Anaconda if using Sublime is another good option.
- **Etiquette: Double quotes**
    - " = yes, ' = no.
- **Etiquette: Napoleon docstrings**
    - Any docstrings are made in Google Napoleon format. See [Napoleon](https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html) for details.
- **Etiquette: Semantic Versioning**
    - This project follows [semantic versioning](http://semver.org).
- **Etiquette: Underscore means private**
    - Anything prefixed with an underscore means that it is internal to Qt.py and not for public consumption.

**Running tests**

Due to the nature of multiple bindings and multiple interpreter support, setting up a development environment in which to properly test your contraptions can be challenging. So here is a guide for how to do just that using **Docker**.

With Docker setup, here's what you do. Please note this will pull down a ~1 GB image.

```bash
cd Qt.py

# Run nosetests (Linux/OSX)
docker run --rm -v $(pwd):/Qt.py -e PYTHON=2.7 fredrikaverpil/qt.py:2018
docker run --rm -v $(pwd):/Qt.py -e PYTHON=3.4 fredrikaverpil/qt.py:2018
docker run --rm -v $(pwd):/Qt.py -e PYTHON=3.5 fredrikaverpil/qt.py:2018
docker run --rm -v $(pwd):/Qt.py -e PYTHON=3.6 fredrikaverpil/qt.py:2018

# Run nosetests (Windows)
docker run --rm -v %CD%:/Qt.py -e PYTHON=2.7 fredrikaverpil/qt.py:2018
docker run --rm -v %CD%:/Qt.py -e PYTHON=3.4 fredrikaverpil/qt.py:2018
docker run --rm -v %CD%:/Qt.py -e PYTHON=3.5 fredrikaverpil/qt.py:2018
docker run --rm -v %CD%:/Qt.py -e PYTHON=3.6 fredrikaverpil/qt.py:2018

# Doctest: test_caveats.test_1_qtgui_qabstractitemmodel_createindex ... ok
# Doctest: test_caveats.test_2_qtgui_qabstractitemmodel_createindex ... ok
# Doctest: test_caveats.test_3_qtcore_qitemselection ... ok
# ...
#
# ----------------------------------------------------------------------
# Ran 21 tests in 7.799s
#
# OK
```

Now both you and Github Actions are operating on the same assumptions which means that when the tests pass on your machine, they pass on Github Actions. And everybody wins!

For details on the Docker image for testing, see [`DOCKER.md`](DOCKER.md).

See [`CONTRIBUTING.md`](CONTRIBUTING.md) for more of the good stuff.

**Upload to PyPI**

To make a new release onto PyPI, you'll need to be mottosso and type this.

```bash
cd Qt.py
python .\setup.py sdist bdist_wheel
python -m twine upload .\dist\*
```

### Qt 6 Transition Guide

| Replace | With | Notes
|:--------|:-----|:----------------------------
| `QFont().setWeight(...)` | `QtCompat.QFont.setWeight(font, ...)`
| `QFont().setWeight(QFont().Bold)` | `QFont().setWeight(QFont.Bold)` | Instance of class doesn't have the enums, apparently
| `QEvent().Resize` | `QEvent.Resize` | Instance of class doesn't have the enums, seems to apply overall
| `QtCore.Qt.MidButton`  | `QtCompat.QtCore.Qt.MidButton`
| `QLabel.setPixmap(str)` | `QLabel.setPixmap(QPixmap())` | Can't take a string anymore (tested in Maya 2025.0)
| `QModelIndex.child` | `QModel.index` | This one is apparently from Qt 4 and should not have been in Qt.py to begin with
| | Submit your known issues here! |

##### Removed Members

Many members were removed from Qt.py due to no longer existing in PySide 6.

> If you find where they went, or think some were removed in error, please submit a pull-request!

```json
"QtCore": [
    "QAbstractState",
    "QAbstractTransition",
    "QEventTransition",
    "QFinalState",
    "QSignalTransition",
    "QTextCodec",
    "QTextDecoder",
    "QTextEncoder",
    "QtCriticalMsg",
    "QtDebugMsg",
    "QtFatalMsg",
    "QtSystemMsg",
    "QtWarningMsg",
    "qChecksum",
    "QPictureIO",
],
"QtMultimedia": [
    "QAbstractVideoBuffer",
    "QAbstractVideoSurface",
    "QAudio",
    "QAudioDeviceInfo",
    "QAudioFormat",
    "QAudioInput",
    "QAudioOutput",
    "QVideoFrame",
    "QVideoSurfaceFormat"
],
"QtNetwork": [
    "QNetworkConfiguration",
    "QNetworkConfigurationManager",
    "QNetworkSession",
],
"QtOpenGL": [
    "QGL",
    "QGLContext",
    "QGLFormat",
    "QGLWidget"
],
"QtSql": [
    "QSql",
    "QSqlDatabase",
    "QSqlDriver",
    "QSqlDriverCreatorBase",
    "QSqlError",
    "QSqlField",
    "QSqlIndex",
    "QSqlQuery",
    "QSqlQueryModel",
    "QSqlRecord",
    "QSqlRelation",
    "QSqlRelationalDelegate",
    "QSqlRelationalTableModel",
    "QSqlResult",
    "QSqlTableModel"
],
"QtSvg": [
    "QSvgGenerator",
    "QSvgRenderer",
],
"QtWidgets": [
    "QActionGroup",
    "QDesktopWidget",
    "QDirModel",
    "QKeyEventTransition",
    "QMouseEventTransition",
    "QUndoCommand",
    "QUndoGroup",
    "QUndoStack",
],
"QtX11Extras": [
    "QX11Info"
],
"QtXml": [
    "QXmlAttributes",
    "QXmlContentHandler",
    "QXmlDTDHandler",
    "QXmlDeclHandler",
    "QXmlDefaultHandler",
    "QXmlEntityResolver",
    "QXmlErrorHandler",
    "QXmlInputSource",
    "QXmlLexicalHandler",
    "QXmlLocator",
    "QXmlNamespaceSupport",
    "QXmlParseException",
    "QXmlReader",
    "QXmlSimpleReader"
],
"QtXmlPatterns": [
    "QAbstractMessageHandler",
    "QAbstractUriResolver",
    "QAbstractXmlNodeModel",
    "QAbstractXmlReceiver",
    "QSourceLocation",
    "QXmlFormatter",
    "QXmlItem",
    "QXmlName",
    "QXmlNamePool",
    "QXmlNodeModelIndex",
    "QXmlQuery",
    "QXmlResultItems",
    "QXmlSchema",
    "QXmlSchemaValidator",
    "QXmlSerializer"
]
```

##### Static Members Missing from Instances

An overall change is that instances of classes, like `QFont()` no longer provides access to static members, such as `QFont.Bold`. So things like:

```py
font = QFont()
font.setWeight(font.Bold)
```

Must be replaced with:

```py
font = QFont()
font.setWeight(QFont.Bold)
```

Or:

```py
font.setWeight(type(font).Bold)
```

Tedious and seemingly unnecessary.. But there you have it!

##### Notes

Qt.py 1.4.0, released in May 2024, added support for Qt 6 whilst preserving compatibility with Qt 4 and 5. That means that in most cases, code you've already written for Qt 4 or 5 will now continue to work with Qt 6, such as Maya 2025.

However, some changes between 5 and 6 require up-front work by you the developer to make your codebase run on Qt 6 whilst continuing to run on Qt 4 and 5.

The above is what we know, please do submit issues and pull-request with what else you find!

- https://github.com/mottosso/Qt.py/issues/new

**See also**

The official PySide2 to PySide6 transition guide, which is especially helpful since Qt.py is modeled after PySide2.

- https://doc.qt.io/qtforpython-6/gettingstarted/porting_from2.html


# PCF Tile Generator

PCF Tile Generator is a suite of tools to help you develop, package, test,
and deploy services and other add-ons to Pivotal Cloud Foundry. The tile generator
uses templates and patterns that are based on years of experience integrating
third-party services into Cloud Foundry, and eliminates much of the need for
you to have intimate knowledge of all the tools involved.

- Documentation: [Pivotal Documentation](http://docs.pivotal.io/tiledev/tile-generator.html)
- PCF Tile Developers Guide: [Pivotal Documentation](http://docs.pivotal.io/tiledev/index.html)
- Roadmap: [Github Issues](https://github.com/cf-platform-eng/tile-generator/issues)
- CI Pipeline: [Runway](https://runway-ci.eng.vmware.com/teams/ppe-isv/pipelines/tile-generator)

## Continuous Integration

GCP project used in CI - **isv-tile-partners**

The master branch of this repository is being monitored by
[this Runway pipeline](https://runway-ci.eng.vmware.com/teams/ppe-isv/pipelines/tile-generator).
The pipeline verifies that:

- The tile generator passes all unit tests in `tile_generator/*_unittest.py`
- The tile generator successfully builds the sample tile in `sample`
- The generated tile passes all acceptance tests in `ci/acceptance-tests`
- The generated tile successfully deploys to a current version of PCF
- The deployed tile passes all deployment tests in `ci/deployment-tests`

## Updating pipeline.yml
- After updating the pipeline template file - pipeline.yml.jinja2, please run the below script to generate the pipeline file from inside the ci directory
```
python3 generate_pipeline_yml.py
```

To target the pipeline run the following command

```
fly login -t <desired_target_name> -c https://runway-ci.eng.vmware.com -n ppe-isv
```

You need to be a member of the ppe-isv team for the above command to work.

## Contributing to the Tile Generator

We welcome comments, questions, and contributions from community members. Please consider
the following ways to contribute:

- File Github issues for questions, bugs and new features and comment and vote on the ones that you are interested in.
- If you want to contribute code, please make your code changes on a fork of this repository and submit a
pull request to the master branch of tile-generator. We strongly suggest that you first file an issue to
let us know of your intent, or comment on the issue you are planning to address.

### Development

For development, it is useful to install the tile-generator package in
*editable* mode. That is, you can install the tile-generator package
in a way that points to your local repository, so that your code
changes are immediately available through the `tile` or `pcf`
commands. To do this, run this command in your tile-generator
repository directory:

```
./install-git-hook.sh
pip install -e .
```

To avoid downloading dependencies on every `tile build`:
1. `cd sample`
2. `mkdir cache`
3. `tile build --cache cache`

Run indiv

Before executing `./scripts/run_local_tests.sh` install virtualenv with `pip install virtualenv`

Then to execute all test using the cache from the project root use:
`./scripts/run_local_tests.sh withcache`

### Note: Mac Binaries are no longer supported

Tile generator cli no longer releases new Mac binaries. Check the [commit](https://github.com/cf-platform-eng/tile-generator/commit/1e8db6fb25f1c0e499965df0a113818188548d5b) that removed support for Mac support. MacStadium account has been cancelled and we currently don't have a way to test tile generator cli Mac binaries.


# LEGO

> Open source backend for abakus.no, frontend located at [webkom/lego-webapp](https://github.com/webkom/lego-webapp)

[![MIT](https://badgen.net/badge/license/MIT/blue)](https://en.wikipedia.org/wiki/MIT_License)
[![last commit](https://badgen.net/github/last-commit/webkom/lego/)](https://github.com/webkom/lego/commits/master)
[![contributors](https://badgen.net/github/contributors/webkom/lego)](https://github.com/webkom/lego/graphs/contributors)
[![Build Status](https://ci.webkom.dev/api/badges/webkom/lego/status.svg)](https://ci.webkom.dev/webkom/lego)
[![codecov](https://codecov.io/gh/webkom/lego/branch/master/graph/badge.svg?token=4JI1CMu58M)](https://codecov.io/gh/webkom/lego)

> LEGO Er Ganske Oppdelt

## Getting started

LEGO requires `python3.11`, `python3.11-venv`, `docker` and `poetry`. Services like Postgres, Redis, Thumbor and Minio run inside docker.

### Initial setup (only needed once)

```bash
$ git clone git@github.com:webkom/lego.git && cd lego/
$ python3 -m venv venv
$ echo "from .development import *" > lego/settings/local.py
$ source venv/bin/activate
$ poetry install
$ docker compose up -d
$ python manage.py initialize_development
```

### Activate and run (every time)

```bash
$ docker compose up -d
$ source venv/bin/activate
$ python manage.py runserver
```

#### Notes

```bash
# Note 1: Whenever you switch branches you might need to make minor changes

$ poetry install # If the branch has changes in the dependencies
$ python manage.py migrate # If the branch has a database in another state than yours

# Note 2: When you make changes to models, or constants used by models, you need to create new migrations

$ python manage.py makemigrations # Creates one or more new files that must be commited

# Remember to format generated migrations! (using e.g. `make fixme`)
```

**`poetry.lock` conflicts**

If you have updated dependencies it's likely you might get conflicts in the Poetry lock file.
This solution should resolve most conflicts quite well:

```bash
$ git rebase origin/master

# If conflicts
$ git checkout --theirs poetry.lock

$ poetry lock --no-update

# The conflicts should be resolved
```

> If you get problems it can be a solution to delete the `venv`, and do a fresh setup

## Code Style

This codebase uses the PEP 8 code style. We enforce this with `isort`, `black` & `flake8`. In addition to the standards outlined in PEP 8, we have a few guidelines (see `pyproject.toml` for more info):

Format the code with `isort` & `black`

```bash
$ make fixme
```

To check if it is formatted properly, run:

```bash
$ tox -e isort -e black -e flake8
```

To check if it is typed properly, run:

```bash
$ tox -e mypy
```

## Tests

If you want to run a specific test class you can run

```bash
$ ./manage.py test lego.apps.[APP]
```

You can add flags to speed up the tests

> By adding the `--keepdb` the next time it will go a lot faster to run the tests multiple times.

> By adding the `--parallel` will run multiple tests in parallel using multiple cores.

If you want to check your test coverage, you can do the following

```bash
# Run all tests in LEGO. Remember to add the recommended flags mentioned above
$ tox -e tests --
# or run without tox
$ coverage run --source=lego ./manage.py test

# If you now have multiple coverage files or a .coverage.* file, you'll have to combine it in order to output report
$ coverage combine

# Then you can output the full coverage report
$ coverage report
# or a small one that only contains the things you are interested in
$ coverage report | grep [some string]
```

## Deployment

LEGO runs in `Docker Swarm` and deploys are managed by `Drone` and `Ansible`.

How to deploy:

1.  Make sure the changes are pushed to master and the test passes.
2.  Have you added some new settings in `settings/`? If so, make sure the `Ansible variables` reflects these changes.
3.  We run migrations automatically, make sure they work!
4.  Push to the `build` branch. From master: `git push origin master:build`
5.  Wait for the `build` build to complete. The last step will be `docker build`
6.  Go to [ci.webkom.dev](https://ci.webkom.dev/webkom/lego/) and use the promote feature to deploy the staging/production build.

Ansible will automatically run the playbook for deploying the new build to `staging` or `production` based on the target selected in step 6.

Testing with elasticsearch

### Testing with elasticsearch

By default, development and production uses postgres for search. We can still enable elasticsearch backend in prod, so you can test things locally with elasticsearch. In order to do so, you need to run elasticsearch from `docker-compose.extra.yml` by running `docker-compose -f docker-compose.extra.yml up -d`. Then you need to run lego with the env variable `SEARCH_BACKEND=elasticsearch`. You might need to run the migrate_search and rebuild_index commands to get elasticsearch up to date.

Debugging

### Debugging

If you get an error while installing project dependencies, you might be missing some on your system.

```bash
$ apt-get install libpq-dev python3-dev
```

> For MACOS you need to `brew install postgresql`

If you get an error while running initialize_development mentioning `elasticsearch`, you probably need to run the following code, and then start over from `docker-compose up -d`. [Read why and how to make it permanent on Elasticsearch docs](https://www.elastic.co/guide/en/elasticsearch/reference/current/vm-max-map-count.html).

```bash
$ sysctl -w vm.max_map_count=262144
```

If you get ld: library not found for -lssl

```
export LDFLAGS="-L/usr/local/opt/openssl/lib"
```

When changing the user fixtures one must load new fixtures

```
./manage.py load_fixtures --generate
```

An overview of the available users for development can be found in [this PR](https://github.com/webkom/lego/pull/1913)


# API de Series de Tiempo

[![Coverage Status](https://coveralls.io/repos/github/datosgobar/series-tiempo-ar-api/badge.svg?branch=master)](https://coveralls.io/github/datosgobar/series-tiempo-ar-api?branch=master)
[![Build Status](https://travis-ci.org/datosgobar/series-tiempo-ar-api.svg?branch=master)](https://travis-ci.org/datosgobar/series-tiempo-ar-api)
[![GitHub tag](https://img.shields.io/github/tag/datosgobar/series-tiempo-ar-api.svg)]()

Aplicación distribuible de la API de Series de Tiempo del [Paquete de Apertura de Datos de la República Argentina](http://paquete-apertura-datos.readthedocs.io/es/stable/).

* Versión python: 3.6
* Licencia: MIT license
* Release status: `beta`
* Documentación: [https://series-tiempo-ar-api.readthedocs.io](https://series-tiempo-ar-api.readthedocs.io)

## Instalación

Ver documentación de [instalación de la aplicación](docs/developers/development.md).

## Uso rápido

*Tipo de cambio, índice de precios núcleo (variación porcentual) e índice de precios nivel general (variación porcentual) desde Enero de 2016, en valores mensuales*

```
/series/?ids=138.1_PAPDE_0_M_41,103.1_I2N_2016_M_15:percent_change,103.1_I2N_2016_M_19:percent_change&collapse=month&format=csv&start_date=2016-01-01
```

indice_tiempo	pesos_argentinos_por_dolar_estadounidense	ipc_2016_nucleo	ipc_2016_nivgeneral

2016-01-01	13.6099238

2016-02-01	14.7951857

2016-03-01	14.8990696

2016-04-01	14.3879762

2016-05-01	14.1183   	0.0265777	0.0419337

2016-06-01	14.1542409	0.0301247	0.0307591

2016-07-01	14.8882952	0.0187154	0.0204675

2016-08-01	14.8339304	0.0165157	0.0020196

2016-09-01	15.1174273	0.0154869	0.0114914

2016-10-01	15.1745429	0.0179986	0.0235933

2016-11-01	15.3529636	0.0171879	0.0161842

2016-12-01	15.8815   	0.0171243	0.0119757

2017-01-01	15.9102773	0.013389 	0.01313

2017-02-01	15.580245 	0.0184608	0.0246316

2017-03-01	15.5240391	0.0182095	0.0236416

2017-04-01	15.33552  	0.0229158	0.0263366

2017-05-01	15.7173087	0.0160246	0.0128313

2017-06-01	16.1231909	0.0152262	0.0138837

2017-07-01	17.1859524	0.0176384	0.0171937

2017-08-01	17.414913 	0.0150374	0.0147753

2017-09-01	17.2411857	0.017578 	0.0204363

2017-10-01	17.4550318

[Descargar ejemplo](https://github.com/datosgobar/series-tiempo-ar-api/raw/master/docs/assets/data-example-1.csv)

Ver [documentación completa](https://datosgobar.github.io/series-tiempo-ar-api/)

## ¿Dónde encontrar los ids y otros metadatos de las series?

En http://www.datos.gob.ar podés encontrar la [base completa de series de tiempo](http://datos.gob.ar/dataset/base-series-tiempo-administracion-publica-nacional) y [descargar la lista de series](http://infra.datos.gob.ar/catalog/modernizacion/dataset/1/distribution/1.2/download/series-tiempo-metadatos.csv) disponibles para buscar cuáles consultar a la API.

También podés descargarte de ahí [todos los valores de la base completa](http://infra.datos.gob.ar/catalog/modernizacion/dataset/1/distribution/1.3/download/series-tiempo-valores.csv), en lugar de usar la API.

## Términos y condiciones de uso

La aplicación se publica actualmente como una versión `beta`. Ver detalle del [acuerdo de nivel de servicio]() (*TODO: escribir versión inicial de SLA*).

Tanto las funcionalidades e interfaz de la API como la arquitectura interna podrían sufrir modificaciones significativas en las próximas versiones.

Todo el código e instrucciones de instalación se publican actualmente sin condiciones de uso más que la cita de la fuente, y sin garantías ni soporte por parte del equipo de [Datos Argentina](datosgobar.github.io) para cualquier actor gubernamental, civil o privado que quiera instalar su propio servicio web de series de tiempo.

Se aclara al usuario desarrollador que todo el modelo de datos y metadatos, así como la arquitectura de la aplicación, están estrechamente basados en la [versión 1.1 del Perfil de Metadatos](http://paquete-apertura-datos.readthedocs.io/es/0.2.0/guia_metadatos.html) de la Política de Apertura de Datos de la Administración Pública Nacional de Argentina.

## Contacto

Te invitamos a [crearnos un issue](https://github.com/datosgobar/series-tiempo-ar-api/issues/new?labels=pedido-comunidad) en caso de que encuentres algún bug o tengas feedback de alguna parte de `series-tiempo-ar-api` o sobre el servicio web.

Para todo lo demás, podés mandarnos tu comentario o consulta a [datosargentina@jefatura.gob.ar](mailto:datosargentina@jefatura.gob.ar).


# pydov <img src="docs/_static/img/logo.png" align="right" alt="" width="120">

[![CI](https://github.com/DOV-Vlaanderen/pydov/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/DOV-Vlaanderen/pydov/actions/workflows/ci.yml) [![Documentation Status](https://readthedocs.org/projects/pydov/badge/?version=latest)](https://pydov.readthedocs.io/en/latest/?badge=latest) [![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active) [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.2788680.svg)](https://doi.org/10.5281/zenodo.2788680) [![pyOpenSci](https://img.shields.io/badge/PyOpenSci-Peer%20Reviewed-success.svg)](https://github.com/pyOpenSci/software-review/issues/19)

pydov is a Python package to query and download data from [Databank Ondergrond Vlaanderen (DOV)](https://www.dov.vlaanderen.be). It is hosted on [GitHub](https://github.com/DOV-Vlaanderen/pydov) and development is coordinated by Databank Ondergrond Vlaanderen (DOV). DOV aggregates data about soil, subsoil and groundwater of Flanders and makes them publicly available. Interactive and human-readable extraction and querying of the data is provided by a [web application](https://www.dov.vlaanderen.be/portaal/?module=verkenner#ModulePage), whereas the focus of this package is to **support machine-based extraction and conversion of the data**.

To get started, see the documentation at https://pydov.readthedocs.io.

Please note that downloading DOV data with pydov is governed by the same [disclaimer](https://www.dov.vlaanderen.be/page/disclaimer) that applies to the other DOV services. Be sure to consult it when using DOV data with pydov.

## Installation

You can install `pydov` stable using pip:

```shell script
pip install pydov
```

Or clone the [git repository](https://github.com/DOV-Vlaanderen/pydov) and install with `python setup.py install` to get the latest snapshot from the master branch.

To contribute to the code, make sure to install the package and all of the development dependencies enlisted in the
[requirements_dev.txt](requirements_dev.txt) file. First, clone the [git repository](https://github.com/DOV-Vlaanderen/pydov).
We advice to use an Python development environment, for example with [conda](https://docs.conda.io/en/latest/miniconda.html) or
[virtualenv](https://virtualenv.pypa.io/en/latest/). Activate the (conda/virtualenv) environment and
install the package in development mode:

```shell script
pip install -e .[devs]
```

Need more detailed instructions? Check out the [installation instructions](https://pydov.readthedocs.io/en/stable/installation.html) and the [development guidelines](https://pydov.readthedocs.io/en/stable/development.html).

## Quick start

Read the [quick start](https://pydov.readthedocs.io/en/stable/quickstart.html) from the docs or jump straight in:

```python
from pydov.search.boring import BoringSearch
from pydov.util.location import Within, Box

from owslib.fes2 import PropertyIsGreaterThan

boringsearch = BoringSearch()

dataframe = boringsearch.search(
    query=PropertyIsGreaterThan(propertyname='diepte_tot_m', literal='550'),
    location=Within(Box(107500, 202000, 108500, 203000))
)
```

The resulting dataframe contains the information on boreholes (boringen) within the provided bounding box (as defined by the `location` argument)
with a depth larger than 550m:
```
>>> dataframe
                                         pkey_boring     boornummer         x         y  mv_mtaw  start_boring_mtaw gemeente  diepte_boring_van  diepte_boring_tot datum_aanvang uitvoerder  boorgatmeting  diepte_methode_van  diepte_methode_tot boormethode
0  https://www.dov.vlaanderen.be/data/boring/1989...  kb14d40e-B777  108015.0  202860.0      5.0                5.0     Gent                0.0              660.0    1989-01-25   onbekend          False                 0.0               660.0    onbekend
1  https://www.dov.vlaanderen.be/data/boring/1972...  kb14d40e-B778  108090.0  202835.0      5.0                5.0     Gent                0.0              600.0    1972-05-17   onbekend          False                 0.0               600.0    onbekend
```

## Documentation

Full documentation of `pydov` can be found on our [ReadTheDocs page](https://pydov.readthedocs.io).

## Contributing

You do not need to be a code expert to contribute to this project as there are several ways you can contribute to
this project. Have a look at the [contributing page](https://pydov.readthedocs.io/en/latest/contributing.html).

## Meta

- We welcome [contributions](.github/CONTRIBUTING.rst) including bug reports.
- License: MIT
- Citation information can be found on [Zenodo](https://doi.org/10.5281/zenodo.2788680).
- Please note that this project is released with a [Contributor Code of Conduct](.github/CODE_OF_CONDUCT.rst). By participating in this project you agree to abide by its terms.
- Also note that downloading DOV data with pydov is governed by the same [disclaimer](https://www.dov.vlaanderen.be/page/disclaimer) that applies to the other DOV services. Be sure to consult it when using DOV data with pydov.


Welcome to Powderday!

Powderday is a dust radiative transfer package designed to interface
with galaxy formation simulations in order to produce spectral energy
distributions, as well as realistic images.

For documentation, please see the docs at:

[http://powderday.readthedocs.org](http://powderday.readthedocs.org)

The manual contains full installation instructions.


SeleniumLibrary
===============

.. contents::

Introduction
------------

SeleniumLibrary_ is a web testing library for `Robot Framework`_ that
utilizes the Selenium_ tool internally. The project is hosted on GitHub_
and downloads can be found from PyPI_.

SeleniumLibrary currently works with Selenium 4. It supports Python 3.8 through 3.11.
In addition to the normal Python_ interpreter, it works also
with PyPy_.

SeleniumLibrary is based on the "old SeleniumLibrary" that was forked to
Selenium2Library and then later renamed back to SeleniumLibrary.
See the `VERSIONS.rst`_ for more information about different versions and the
overall project history.

.. image:: https://img.shields.io/pypi/v/robotframework-seleniumlibrary.svg?label=version
   :target: https://pypi.python.org/pypi/robotframework-seleniumlibrary

.. image:: https://img.shields.io/pypi/dm/robotframework-seleniumlibrary.svg
   :target: https://pypi.python.org/pypi/robotframework-seleniumlibrary

.. image:: https://img.shields.io/pypi/l/robotframework-seleniumlibrary.svg
   :target: https://www.apache.org/licenses/LICENSE-2.0

.. image:: https://github.com/robotframework/SeleniumLibrary/actions/workflows/CI.yml/badge.svg?branch=master
    :target: https://github.com/robotframework/SeleniumLibrary/actions/workflows/CI.yml

Keyword Documentation
---------------------
See `keyword documentation`_ for available keywords and more information
about the library in general.

Installation
------------

The recommended installation method is using pip_::

    pip install --upgrade robotframework-seleniumlibrary

Running this command installs also the latest Selenium and Robot Framework
versions, but you still need to install `browser drivers`_ separately.
The ``--upgrade`` option can be omitted when installing the library for the
first time.

It is possible to install directly from the GitHub_ repository. To install
latest source from the master branch, use this command::

    pip install git+https://github.com/robotframework/SeleniumLibrary.git

Please note that installation will take some time, because ``pip`` will
clone the SeleniumLibrary_ project to a temporary directory and then
perform the installation.

See `Robot Framework installation instructions`_ for detailed information
about installing Python and Robot Framework itself. For more details about
using ``pip`` see `its own documentation <pip_>`__.

Browser drivers
---------------

After installing the library, you still need to install browser and
operating system specific browser drivers for all those browsers you
want to use in tests. These are the exact same drivers you need to use with
Selenium also when not using SeleniumLibrary. More information about
drivers can be found from `Selenium documentation`__.

The general approach to install a browser driver is downloading a right
driver, such as ``chromedriver`` for Chrome, and placing it into
a directory that is in PATH__. Drivers for different browsers
can be found via Selenium documentation or by using your favorite
search engine with a search term like ``selenium chrome browser driver``.
New browser driver versions are released to support features in
new browsers, fix bug, or otherwise, and you need to keep an eye on them
to know when to update drivers you use.

Alternatively, you can use a tool called WebdriverManager__ which can
find the latest version or when required, any version of appropriate
webdrivers for you and then download and link/copy it into right
location. Tool can run on all major operating systems and supports
downloading of Chrome, Firefox, Opera & Edge webdrivers.

Here's an example:

.. code:: bash

      pip install webdrivermanager
      webdrivermanager firefox chrome --linkpath /usr/local/bin

__ https://seleniumhq.github.io/selenium/docs/api/py/index.html#drivers
__ https://en.wikipedia.org/wiki/PATH_(variable)
__ https://github.com/omenia/webdrivermanager

Usage
-----

To use SeleniumLibrary in Robot Framework tests, the library needs to
first be imported using the ``Library`` setting as any other library.
The library accepts some import time arguments, which are documented
in the `keyword documentation`_ along with all the keywords provided
by the library.

When using Robot Framework, it is generally recommended to write as
easy-to-understand tests as possible. The keywords provided by
SeleniumLibrary is pretty low level, though, and often require
implementation-specific arguments like element locators to be passed
as arguments. It is thus typically a good idea to write tests using
Robot Framework's higher-level keywords that utilize SeleniumLibrary
keywords internally. This is illustrated by the following example
where SeleniumLibrary keywords like ``Input Text`` are primarily
used by higher-level keywords like ``Input Username``.

.. code:: robotframework

    *** Settings ***
    Documentation     Simple example using SeleniumLibrary.
    Library           SeleniumLibrary

    *** Variables ***
    ${LOGIN URL}      http://localhost:7272
    ${BROWSER}        Chrome

    *** Test Cases ***
    Valid Login
        Open Browser To Login Page
        Input Username    demo
        Input Password    mode
        Submit Credentials
        Welcome Page Should Be Open
        [Teardown]    Close Browser

    *** Keywords ***
    Open Browser To Login Page
        Open Browser    ${LOGIN URL}    ${BROWSER}
        Title Should Be    Login Page

    Input Username
        [Arguments]    ${username}
        Input Text    username_field    ${username}

    Input Password
        [Arguments]    ${password}
        Input Text    password_field    ${password}

    Submit Credentials
        Click Button    login_button

    Welcome Page Should Be Open
        Title Should Be    Welcome Page

The above example is a slightly modified version of an example in a
`demo project`_ that illustrates using Robot Framework and SeleniumLibrary.
See the demo for more examples that you can also execute on your own
machine. For more information about Robot Framework test data syntax in
general see the `Robot Framework User Guide`_.

Extending SeleniumLibrary
-------------------------
Before creating your own library which extends the ``SeleniumLibrary``, please consider would
the extension be also useful also for general usage. If it could be useful also for general
usage, please create a new issue describing the enhancement request and even better if the
issue is backed up by a pull request.

If the enhancement is not generally useful, example solution is domain specific, then the
SeleniumLibrary offers public APIs which can be used to build its own plugins and libraries.
Plugin API allows us to add new keywords, modify existing keywords and modify the internal
functionality of the library. Also new libraries can be built on top of the
SeleniumLibrary. Please see `extending documentation`_ for more details about the
available methods and for examples how the library can be extended.

Community
---------

If the provided documentation is not enough, there are various community channels
available:

- ``#seleniumlibrary`` and ``#seleniumlibrary-dev`` channels in
  Robot Framework `Slack community`_
- `Robot Framework forum`_ has channel for SeleniumLibrary.
- SeleniumLibrary `issue tracker`_ for bug reports and concrete enhancement
  requests
- `Other community channels`_ including paid support

.. _Robot Framework: https://robotframework.org
.. _Selenium: https://www.seleniumhq.org/
.. _SeleniumLibrary: https://github.com/robotframework/SeleniumLibrary
.. _pip: http://pip-installer.org
.. _PyPI: https://pypi.python.org/pypi/robotframework-seleniumlibrary
.. _GitHub: https://github.com/robotframework/SeleniumLibrary
.. _Keyword Documentation: https://robotframework.org/SeleniumLibrary/SeleniumLibrary.html
.. _Python: https://python.org
.. _PyPy: https://pypy.org
.. _demo project: https://github.com/robotframework/WebDemo
.. _Robot Framework User Guide: https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html
.. _Robot Framework installation instructions: https://github.com/robotframework/robotframework/blob/master/INSTALL.rst
.. _extending documentation: https://github.com/robotframework/SeleniumLibrary/blob/master/docs/extending/extending.rst
.. _Slack community: https://robotframework-slack-invite.herokuapp.com
.. _Robot Framework forum: https://forum.robotframework.org/
.. _issue tracker: https://github.com/robotframework/SeleniumLibrary/issues
.. _Other community channels: https://robotframework.org/#community
.. _VERSIONS.rst: https://github.com/robotframework/SeleniumLibrary/blob/master/VERSIONS.rst


# Helios Election System

Helios is an end-to-end verifiable voting system.

[![Travis Build Status](https://travis-ci.org/benadida/helios-server.svg?branch=master)](https://travis-ci.org/benadida/helios-server)

[![Stories in Ready](https://badge.waffle.io/benadida/helios-server.png?label=ready&title=Ready)](https://waffle.io/benadida/helios-server)


# pyDAL

pyDAL is a pure Python Database Abstraction Layer.

It dynamically generates the SQL/noSQL in realtime using the specified dialect for the database backend, so that you do not have to write SQL code or learn different SQL dialects (the term SQL is used generically), and your code will be portable among different types of databases.

pyDAL comes from the original web2py's DAL, with the aim of being compatible with any Python program. pyDAL doesn't require web2py and can be used in any Python context.

[![pip version](https://img.shields.io/pypi/v/pydal.svg?style=flat-square)](https://pypi.python.org/pypi/pydal)
[![Build Status](https://img.shields.io/travis/web2py/pydal/master.svg?style=flat-square&label=Travis-CI)](https://travis-ci.com/web2py/pydal)
[![Coverage Status](https://img.shields.io/codecov/c/github/web2py/pydal.svg?style=flat-square)](https://codecov.io/github/web2py/pydal)
[![API Docs Status](https://readthedocs.org/projects/pydal/badge/?version=latest&style=flat-square)](http://pydal.rtfd.org/)

## Installation

You can install pyDAL using `pip`:

```bash
pip install pyDAL
```

## Usage and Documentation

Here is a quick example:

```pycon
>>> from pydal import DAL, Field
>>> db = DAL('sqlite://storage.db')
>>> db.define_table('thing', Field('name'))
>>> db.thing.insert(name='Chair')
>>> query = db.thing.name.startswith('C')
>>> rows = db(query).select()
>>> print rows[0].name
Chair
>>> db.commit()
```

The complete documentation is available on http://www.web2py.com/books/default/chapter/29/06/the-database-abstraction-layer

## What's in the box?

A little *taste* of pyDAL features:

* Transactions
* Aggregates
* Inner Joins
* Outer Joins
* Nested Selects

## Which databases are supported?

pyDAL supports the following databases:

* SQLite
* MySQL
* PostgreSQL
* MSSQL
* FireBird
* Oracle
* DB2
* Ingres
* Sybase
* Informix
* Teradata
* Cubrid
* SAPDB
* IMAP
* MongoDB

## License

pyDAL is released under the BSD-3c License.  For further details, please check the `LICENSE` file.


# GraphQL-core 3

GraphQL-core 3 is a Python 3.6+ port of [GraphQL.js](https://github.com/graphql/graphql-js),
the JavaScript reference implementation for [GraphQL](https://graphql.org/),
a query language for APIs created by Facebook.

[![PyPI version](https://badge.fury.io/py/graphql-core.svg)](https://badge.fury.io/py/graphql-core)
[![Documentation Status](https://readthedocs.org/projects/graphql-core-3/badge/)](https://graphql-core-3.readthedocs.io)
![Test Status](https://github.com/graphql-python/graphql-core/actions/workflows/test.yml/badge.svg)
![Lint Status](https://github.com/graphql-python/graphql-core/actions/workflows/lint.yml/badge.svg)
[![Code Style](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black)

An extensive test suite with over 2300 unit tests and 100% coverage comprises a
replication of the complete test suite of GraphQL.js, making sure this port is
reliable and compatible with GraphQL.js.

The current stable version 3.2.3 of GraphQL-core is up-to-date with GraphQL.js
version 16.6.0 and supports Python version 3.7 and newer.

You can also try out the latest alpha version 3.3.0a5 of GraphQL-core
which is up-to-date with GraphQL.js version 17.0.0a2.
Please note that this new minor version of GraphQL-core does not support
Python 3.6 anymore.

Note that for various reasons, GraphQL-core does not use SemVer like GraphQL.js.
Changes in the major version of GraphQL.js are reflected in the minor version of
GraphQL-core instead. This means there can be breaking changes in the API
when the minor version changes, and only patch releases are fully backward compatible.
Therefore, we recommend something like `=~ 3.2.0` as version specifier
when including GraphQL-core as a dependency.

## Documentation

A more detailed documentation for GraphQL-core 3 can be found at
[graphql-core-3.readthedocs.io](https://graphql-core-3.readthedocs.io/).

The documentation for GraphQL.js can be found at [graphql.org/graphql-js/](https://graphql.org/graphql-js/).

The documentation for GraphQL itself can be found at [graphql.org](https://graphql.org/).

There will be also [blog articles](https://cito.github.io/tags/graphql/) with more usage
examples.

## Getting started

A general overview of GraphQL is available in the
[README](https://github.com/graphql/graphql-spec/blob/main/README.md) for the
[Specification for GraphQL](https://github.com/graphql/graphql-spec). That overview
describes a simple set of GraphQL examples that exist as [tests](tests) in this
repository. A good way to get started with this repository is to walk through that
README and the corresponding tests in parallel.

## Installation

GraphQL-core 3 can be installed from PyPI using the built-in pip command:

    python -m pip install graphql-core

You can also use [poetry](https://github.com/python-poetry/poetry) for installation in a
virtual environment:

    poetry install

## Usage

GraphQL-core provides two important capabilities: building a type schema and
serving queries against that type schema.

First, build a GraphQL type schema which maps to your codebase:

```python
from graphql import (
    GraphQLSchema, GraphQLObjectType, GraphQLField, GraphQLString)

schema = GraphQLSchema(
    query=GraphQLObjectType(
        name='RootQueryType',
        fields={
            'hello': GraphQLField(
                GraphQLString,
                resolve=lambda obj, info: 'world')
        }))
```

This defines a simple schema, with one type and one field, that resolves to a fixed
value. The `resolve` function can return a value, a co-routine object or a list of
these. It takes two positional arguments; the first one provides the root or the
resolved parent field, the second one provides a `GraphQLResolveInfo` object which
contains information about the execution state of the query, including a `context`
attribute holding per-request state such as authentication information or database
session. Any GraphQL arguments are passed to the `resolve` functions as individual
keyword arguments.

Note that the signature of the resolver functions is a bit different in GraphQL.js,
where the context is passed separately and arguments are passed as a single object.
Also note that GraphQL fields must be passed as a `GraphQLField` object explicitly.
Similarly, GraphQL arguments must be passed as `GraphQLArgument` objects.

A more complex example is included in the top-level [tests](tests) directory.

Then, serve the result of a query against that type schema.

```python
from graphql import graphql_sync

source = '{ hello }'

print(graphql_sync(schema, source))
```

This runs a query fetching the one field defined, and then prints the result:

```python
ExecutionResult(data={'hello': 'world'}, errors=None)
```

The `graphql_sync` function will first ensure the query is syntactically and
semantically valid before executing it, reporting errors otherwise.

```python
from graphql import graphql_sync

source = '{ BoyHowdy }'

print(graphql_sync(schema, source))
```

Because we queried a non-existing field, we will get the following result:

```python
ExecutionResult(data=None, errors=[GraphQLError(
    "Cannot query field 'BoyHowdy' on type 'RootQueryType'.",
    locations=[SourceLocation(line=1, column=3)])])
```

The `graphql_sync` function assumes that all resolvers return values synchronously.
By  using coroutines as resolvers, you can also create results in an asynchronous
fashion with the `graphql` function.

```python
import asyncio
from graphql import (
    graphql, GraphQLSchema, GraphQLObjectType, GraphQLField, GraphQLString)

async def resolve_hello(obj, info):
    await asyncio.sleep(3)
    return 'world'

schema = GraphQLSchema(
    query=GraphQLObjectType(
        name='RootQueryType',
        fields={
            'hello': GraphQLField(
                GraphQLString,
                resolve=resolve_hello)
        }))

async def main():
    query = '{ hello }'
    print('Fetching the result...')
    result = await graphql(schema, query)
    print(result)

asyncio.run(main())
```

## Goals and restrictions

GraphQL-core tries to reproduce the code of the reference implementation GraphQL.js
in Python as closely as possible and to stay up-to-date with the latest development of
GraphQL.js.

GraphQL-core 3 (formerly known as GraphQL-core-next) has been created as a modern
alternative to [GraphQL-core 2](https://github.com/graphql-python/graphql-core-legacy),
a prior work by Syrus Akbary, based on an older version of GraphQL.js and also
targeting older Python versions. Some parts of GraphQL-core 3 have been inspired by
GraphQL-core 2 or directly taken over with only slight modifications, but most of the
code has been re-implemented from scratch, replicating the latest code in GraphQL.js
very closely and adding type hints for Python.

Design goals for the GraphQL-core 3 library were:

* to be a simple, cruft-free, state-of-the-art GraphQL implementation for current
  Python versions
* to be very close to the GraphQL.js reference implementation, while still providing
  a Pythonic API and code style
* to make extensive use of Python type hints, similar to how GraphQL.js used Flow
  (and is now using TypeScript)
* to use [black](https://github.com/ambv/black) to achieve a consistent code style
  while saving time and mental energy for more important matters
  (we are now using [ruff](https://github.com/astral-sh/ruff) instead)
* to replicate the complete Mocha-based test suite of GraphQL.js
  using [pytest](https://docs.pytest.org/)
  with [pytest-describe](https://pypi.org/project/pytest-describe/)

Some restrictions (mostly in line with the design goals):

* requires Python 3.6 or newer (Python 3.7 and newer in latest version)
* does not support some already deprecated methods and options of GraphQL.js
* supports asynchronous operations only via async.io
  (does not support the additional executors in GraphQL-core)

## Integration with other libraries and roadmap

* [Graphene](http://graphene-python.org/) is a more high-level framework for building
  GraphQL APIs in Python, and there is already a whole ecosystem of libraries, server
  integrations and tools built on top of Graphene. Most of this Graphene ecosystem has
  also been created by Syrus Akbary, who meanwhile has handed over the maintenance
  and future development to members of the GraphQL-Python community.

  The current version 2 of Graphene is using Graphql-core 2 as core library for much of
  the heavy lifting. Note that Graphene 2 is not compatible with GraphQL-core 3.
  The  new version 3 of Graphene will use GraphQL-core 3 instead of GraphQL-core 2.

* [Ariadne](https://github.com/mirumee/ariadne) is a Python library for implementing
  GraphQL servers using schema-first approach created by Mirumee Software.

  Ariadne is already using GraphQL-core 3 as its GraphQL implementation.

* [Strawberry](https://github.com/strawberry-graphql/strawberry), created by Patrick
  Arminio, is a new GraphQL library for Python 3, inspired by dataclasses,
  that is also using GraphQL-core 3 as underpinning.

## Changelog

Changes are tracked as
[GitHub releases](https://github.com/graphql-python/graphql-core/releases).

## Credits and history

The GraphQL-core 3 library
* has been created and is maintained by Christoph Zwerschke
* uses ideas and code from GraphQL-core 2, a prior work by Syrus Akbary
* is a Python port of GraphQL.js which has been developed by Lee Byron and others
  at Facebook, Inc. and is now maintained
  by the [GraphQL foundation](https://gql.foundation/join/)

Please watch the recording of Lee Byron's short keynote on the
[history of GraphQL](https://www.youtube.com/watch?v=VjHWkBr3tjI)
at the open source leadership summit 2019 to better understand
how and why GraphQL was created at Facebook and then became open sourced
and ported to many different programming languages.

## License

GraphQL-core 3 is
[MIT-licensed](./LICENSE),
just like GraphQL.js.