Merge pull request #1653 from onionshare/pyside6-package

Pyside6 package
This commit is contained in:
Micah Lee 2023-05-21 09:47:18 -07:00 committed by GitHub
commit 8be0290fdf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
54 changed files with 2723 additions and 2757 deletions

View File

@ -1,5 +1,5 @@
name: Build name: Build
run-name: Build win32, win64, mac (Intel) 🚀 run-name: Build win64, mac (Intel) 🚀
on: on:
push: push:
branches: branches:
@ -14,8 +14,13 @@ jobs:
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Install python
uses: actions/setup-python@v4
with:
python-version: '3.10.11'
- name: Install poetry - name: Install poetry
run: C:\hostedtoolcache\windows\Python\3.9.13\x64\python -m pip install poetry run: C:\hostedtoolcache\windows\Python\3.10.11\x64\python -m pip install poetry
- name: Restore cache - poetry - name: Restore cache - poetry
uses: actions/cache@v3 uses: actions/cache@v3
@ -26,8 +31,8 @@ jobs:
- name: Install poetry dependencies - name: Install poetry dependencies
run: | run: |
cd desktop cd desktop
C:\hostedtoolcache\windows\Python\3.9.13\x64\Scripts\poetry install C:\hostedtoolcache\windows\Python\3.10.11\x64\Scripts\poetry install
C:\hostedtoolcache\windows\Python\3.9.13\x64\Scripts\poetry env list --full-path C:\hostedtoolcache\windows\Python\3.10.11\x64\Scripts\poetry env list --full-path
- name: Restore cache - tor - name: Restore cache - tor
uses: actions/cache@v3 uses: actions/cache@v3
@ -36,7 +41,7 @@ jobs:
key: ${{ runner.os }}-win64-tor-${{ hashFiles('desktop/scripts/get-tor.py') }} key: ${{ runner.os }}-win64-tor-${{ hashFiles('desktop/scripts/get-tor.py') }}
- name: Get tor binaries from Tor Browser (64-bit) - name: Get tor binaries from Tor Browser (64-bit)
run: cd desktop && C:\hostedtoolcache\windows\Python\3.9.13\x64\Scripts\poetry run python .\scripts\get-tor.py win64 run: cd desktop && C:\hostedtoolcache\windows\Python\3.10.11\x64\Scripts\poetry run python .\scripts\get-tor.py win64
- name: Restore cache - obfs4proxy - name: Restore cache - obfs4proxy
uses: actions/cache@v3 uses: actions/cache@v3
@ -89,13 +94,13 @@ jobs:
- name: Build OnionShare - name: Build OnionShare
run: | run: |
cd desktop cd desktop
C:\hostedtoolcache\windows\Python\3.9.13\x64\Scripts\poetry run python .\setup-freeze.py build C:\hostedtoolcache\windows\Python\3.10.11\x64\Scripts\poetry run python .\setup-freeze.py build
C:\hostedtoolcache\windows\Python\3.9.13\x64\Scripts\poetry run python .\scripts\build-windows.py cleanup-build C:\hostedtoolcache\windows\Python\3.10.11\x64\Scripts\poetry run python .\scripts\build-windows.py cleanup-build
- name: Compress - name: Compress
shell: pwsh shell: pwsh
run: | run: |
mv desktop\build\exe.win-amd64-3.9\ ~\onionshare-win64 mv desktop\build\exe.win-amd64-3.10\ ~\onionshare-win64
Compress-Archive -LiteralPath ~\onionshare-win64 -DestinationPath ~\onionshare-win64.zip Compress-Archive -LiteralPath ~\onionshare-win64 -DestinationPath ~\onionshare-win64.zip
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v3
@ -103,118 +108,17 @@ jobs:
name: win64-build name: win64-build
path: ~\onionshare-win64.zip path: ~\onionshare-win64.zip
build-win32: # TODO: Someday, build universal2 mac binaries. Right now it's blocked because Github Actions doesn't support
runs-on: windows-latest # M1 Mac VMs: https://github.com/actions/runner-images/issues/2187
steps:
- uses: actions/checkout@v3
- name: Install poetry build-mac-intel:
run: C:\hostedtoolcache\windows\Python\3.9.13\x86\python -m pip install poetry
- name: Restore cache - poetry
uses: actions/cache@v3
with:
path: ~\AppData\Local\pypoetry\Cache\virtualenvs
key: ${{ runner.os }}-win32-poetry-${{ hashFiles('desktop/poetry.lock') }}
- name: Install poetry dependencies
run: |
cd desktop
C:\hostedtoolcache\windows\Python\3.9.13\x86\Scripts\poetry install
C:\hostedtoolcache\windows\Python\3.9.13\x86\Scripts\poetry env list --full-path
- name: Restore cache - tor
uses: actions/cache@v3
with:
path: desktop\build\tor
key: ${{ runner.os }}-win32-tor-${{ hashFiles('desktop/scripts/get-tor.py') }}
- name: Get tor binaries from Tor Browser (32-bit)
run: cd desktop && C:\hostedtoolcache\windows\Python\3.9.13\x86\Scripts\poetry run python .\scripts\get-tor.py win32
- name: Install golang (32-bit)
shell: pwsh
run: |
cd ~\Downloads
Invoke-WebRequest -Uri https://go.dev/dl/go1.19.1.windows-386.msi -OutFile go1.19.1.windows-386.msi
msiexec.exe /i go1.19.1.windows-386.msi /quiet /L*V go-install.log
- name: Restore cache - obfs4proxy
uses: actions/cache@v3
with:
path: desktop\onionshare\resources\tor\obfs4proxy.exe
key: ${{ runner.os }}-win32-obfs4proxy-${{ hashFiles('desktop/scripts/build-pt-obfs4proxy.ps1') }}
- name: Build obfs4proxy
shell: pwsh
run: |
if ((Test-Path -Path 'desktop\onionshare\resources\tor\obfs4proxy.exe') -eq $True) {
Write-Output "obfs4proxy already built"
} else {
$env:PATH = "C:\Program Files (x86)\Go\bin\go;$env:PATH"
cd desktop
.\scripts\build-pt-obfs4proxy.ps1
}
- name: Restore cache - snowflake
uses: actions/cache@v3
with:
path: desktop\onionshare\resources\tor\snowflake-client.exe
key: ${{ runner.os }}-win32-snowflake-${{ hashFiles('desktop/scripts/build-pt-snowflake.ps1') }}
- name: Build snowflake
shell: pwsh
run: |
if ((Test-Path -Path 'desktop\onionshare\resources\tor\snowflake-client.exe') -eq $True) {
Write-Output "snowflake already built"
} else {
$env:PATH = "C:\Program Files (x86)\Go\bin\go;$env:PATH"
cd desktop
.\scripts\build-pt-snowflake.ps1
}
- name: Restore cache - meek
uses: actions/cache@v3
with:
path: desktop\onionshare\resources\tor\meek-client.exe
key: ${{ runner.os }}-win32-meek-${{ hashFiles('desktop/scripts/build-pt-meek.ps1') }}
- name: Build meek
shell: pwsh
run: |
if ((Test-Path -Path 'desktop\onionshare\resources\tor\meek-client.exe') -eq $True) {
Write-Output "meek already built"
} else {
$env:PATH = "C:\Program Files (x86)\Go\bin\go;$env:PATH"
cd desktop
.\scripts\build-pt-meek.ps1
}
- name: Build OnionShare
run: |
cd desktop
C:\hostedtoolcache\windows\Python\3.9.13\x86\Scripts\poetry run python .\setup-freeze.py build
C:\hostedtoolcache\windows\Python\3.9.13\x86\Scripts\poetry run python .\scripts\build-windows.py cleanup-build
- name: Compress
shell: pwsh
run: |
mv desktop\build\exe.win32-3.9\ ~\onionshare-win32
Compress-Archive -LiteralPath ~\onionshare-win32 -DestinationPath ~\onionshare-win32.zip
- uses: actions/upload-artifact@v3
with:
name: win32-build
path: ~\onionshare-win32.zip
build-mac:
runs-on: macos-latest runs-on: macos-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Install Python 3.9.13 (Intel) - name: Install Python 3.10.9 (universal2)
run: | run: |
curl -L https://www.python.org/ftp/python/3.9.13/python-3.9.13-macosx10.9.pkg --output ~/Downloads/python.pkg curl -L https://www.python.org/ftp/python/3.10.9/python-3.10.9-macos11.pkg --output ~/Downloads/python.pkg
sudo installer -pkg ~/Downloads/python.pkg -target / sudo installer -pkg ~/Downloads/python.pkg -target /
- name: Install poetry - name: Install poetry
@ -230,7 +134,7 @@ jobs:
- name: Install poetry dependencies - name: Install poetry dependencies
run: | run: |
cd desktop cd desktop
/Library/Frameworks/Python.framework/Versions/3.9/bin/poetry install /Library/Frameworks/Python.framework/Versions/3.10/bin/poetry install
- name: Restore cache - tor - name: Restore cache - tor
uses: actions/cache@v3 uses: actions/cache@v3
@ -241,7 +145,7 @@ jobs:
- name: Get tor binaries from Tor Browser - name: Get tor binaries from Tor Browser
run: | run: |
cd desktop cd desktop
/Library/Frameworks/Python.framework/Versions/3.9/bin/poetry run python ./scripts/get-tor.py macos /Library/Frameworks/Python.framework/Versions/3.10/bin/poetry run python ./scripts/get-tor.py macos
- name: Restore cache - obfs4proxy - name: Restore cache - obfs4proxy
uses: actions/cache@v3 uses: actions/cache@v3
@ -288,22 +192,31 @@ jobs:
./scripts/build-pt-meek.sh ./scripts/build-pt-meek.sh
fi fi
- name: Install cx_Freeze/PySide6 build dependencies
run: |
brew install libiodbc
cd ~/Downloads
curl -O -L https://github.com/PostgresApp/PostgresApp/releases/download/v2.5.12/Postgres-2.5.12-14.dmg
hdiutil attach Postgres-2.5.12-14.dmg
cp -r /Volumes/Postgres-2.5.12-14/Postgres.app /Applications/
hdiutil detach /Volumes/Postgres-2.5.12-14
- name: Build OnionShare - name: Build OnionShare
run: | run: |
cd desktop cd desktop
/Library/Frameworks/Python.framework/Versions/3.9/bin/poetry run python ./setup-freeze.py build /Library/Frameworks/Python.framework/Versions/3.10/bin/poetry run python ./setup-freeze.py build
/Library/Frameworks/Python.framework/Versions/3.9/bin/poetry run python ./setup-freeze.py bdist_mac /Library/Frameworks/Python.framework/Versions/3.10/bin/poetry run python ./setup-freeze.py bdist_mac
/Library/Frameworks/Python.framework/Versions/3.9/bin/poetry run python ./scripts/build-macos.py cleanup-build /Library/Frameworks/Python.framework/Versions/3.10/bin/poetry run python ./scripts/build-macos.py cleanup-build
- name: Compress - name: Compress
run: | run: |
cd desktop/build cd desktop/build
tar -czvf ~/onionshare-macos.tar.gz OnionShare.app tar -czvf ~/onionshare-macos-intel.tar.gz OnionShare.app
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v3
with: with:
name: mac-build name: mac-build
path: ~/onionshare-macos.tar.gz path: ~/onionshare-macos-intel.tar.gz
build-flatpak: build-flatpak:
runs-on: ubuntu-latest runs-on: ubuntu-latest

2
.gitignore vendored
View File

@ -58,5 +58,7 @@ venv
# other # other
.vscode .vscode
.python-version
onionshare.dist-info onionshare.dist-info
desktop/onionshare/resources/tor desktop/onionshare/resources/tor
TODO*

View File

@ -69,12 +69,12 @@ cd ..
# get onionshare dependencies # get onionshare dependencies
cd pip cd pip
./flatpak-pip-generator $(python3 -c 'import toml; print("\n".join(toml.loads(open("../../onionshare/desktop/pyproject.toml").read())["tool"]["poetry"]["dependencies"]))' |grep -vi onionshare_cli |grep -vi python | grep -vi pyside2 | grep -vi cx_freeze |tr "\n" " ") ./flatpak-pip-generator $(python3 -c 'import toml; print("\n".join(toml.loads(open("../../onionshare/desktop/pyproject.toml").read())["tool"]["poetry"]["dependencies"]))' |grep -vi onionshare_cli |grep -vi python | grep -vi pyside6 | grep -vi cx_freeze |tr "\n" " ")
cd .. cd ..
# convert to yaml # convert to yaml
./flatpak-json2yaml.py -o onionshare-cli.yml poetry/generated-poetry-sources.json ./flatpak-json2yaml.py -o onionshare-cli.yml poetry/generated-poetry-sources.json
./flatpak-json2yaml.py -o onionshare.yml pip/python3-qrcode.json ./flatpak-json2yaml.py -o onionshare.yml pip/python3-modules.json
``` ```
Now, merge `onionshare-cli.yml` and `onionshare.yml` into the Flatpak manifest. Now, merge `onionshare-cli.yml` and `onionshare.yml` into the Flatpak manifest.
@ -150,6 +150,32 @@ This will create:
### macOS release ### macOS release
In order to make a universal2 binary, you must run this one a Mac with Apple Silicon. To keep a clean environment, you can use VM.
Set up the VM like this:
- Install [Homebrew](https://brew.sh/)
- `brew install create-dmg libiodbc`
- Install the latest Python 3.10 from https://www.python.org/downloads/
- Install ARM64 version of Go from https://go.dev/dl/
- Install "Postgres.app with PostgreSQL 14 (Universal)" from https://postgresapp.com/downloads.html (required for cx_Freeze build step)
```sh
cd desktop
python3 -m pip install poetry
/Library/Frameworks/Python.framework/Versions/3.10/bin/poetry install
/Library/Frameworks/Python.framework/Versions/3.10/bin/poetry run python ./scripts/get-tor.py macos
./scripts/build-pt-obfs4proxy.sh
./scripts/build-pt-snowflake.sh
./scripts/build-pt-meek.sh
/Library/Frameworks/Python.framework/Versions/3.10/bin/poetry run python ./setup-freeze.py build
/Library/Frameworks/Python.framework/Versions/3.10/bin/poetry run python ./setup-freeze.py bdist_mac
/Library/Frameworks/Python.framework/Versions/3.10/bin/poetry run python ./scripts/build-macos.py cleanup-build
cd build
tar -czvf ~/onionshare-macos-universal2.tar.gz OnionShare.app
```
Set up the packaging environment: Set up the packaging environment:
- Install create-dmg: `brew install create-dmg` - Install create-dmg: `brew install create-dmg`

View File

@ -1,2 +1,2 @@
# Enable built-in meek-azure bridge # Enable built-in meek-azure bridge
Bridge meek_lite 192.0.2.2:2 97700DFE9F483596DDA6264C4D7DF7641E1E39CE url=https://meek.azureedge.net/ front=ajax.aspnetcdn.com Bridge meek_lite 192.0.2.18:80 BE776A53492E1E044A26F17306E1BC46A55A1625 url=https://meek.azureedge.net/ front=ajax.aspnetcdn.com

View File

@ -6,10 +6,7 @@ Bridge obfs4 193.11.166.194:27020 86AC7B8D430DAC4117E9F42C9EAED18133863AAF cert=
Bridge obfs4 193.11.166.194:27025 1AE2C08904527FEA90C4C4F8C1083EA59FBC6FAF cert=ItvYZzW5tn6v3G4UnQa6Qz04Npro6e81AP70YujmK/KXwDFPTs3aHXcHp4n8Vt6w/bv8cA iat-mode=0 Bridge obfs4 193.11.166.194:27025 1AE2C08904527FEA90C4C4F8C1083EA59FBC6FAF cert=ItvYZzW5tn6v3G4UnQa6Qz04Npro6e81AP70YujmK/KXwDFPTs3aHXcHp4n8Vt6w/bv8cA iat-mode=0
Bridge obfs4 209.148.46.65:443 74FAD13168806246602538555B5521A0383A1875 cert=ssH+9rP8dG2NLDN2XuFw63hIO/9MNNinLmxQDpVa+7kTOa9/m+tGWT1SmSYpQ9uTBGa6Hw iat-mode=0 Bridge obfs4 209.148.46.65:443 74FAD13168806246602538555B5521A0383A1875 cert=ssH+9rP8dG2NLDN2XuFw63hIO/9MNNinLmxQDpVa+7kTOa9/m+tGWT1SmSYpQ9uTBGa6Hw iat-mode=0
Bridge obfs4 37.218.245.14:38224 D9A82D2F9C2F65A18407B1D2B764F130847F8B5D cert=bjRaMrr1BRiAW8IE9U5z27fQaYgOhX1UCmOpg2pFpoMvo6ZgQMzLsaTzzQNTlm7hNcb+Sg iat-mode=0 Bridge obfs4 37.218.245.14:38224 D9A82D2F9C2F65A18407B1D2B764F130847F8B5D cert=bjRaMrr1BRiAW8IE9U5z27fQaYgOhX1UCmOpg2pFpoMvo6ZgQMzLsaTzzQNTlm7hNcb+Sg iat-mode=0
Bridge obfs4 38.229.1.78:80 C8CBDB2464FC9804A69531437BCF2BE31FDD2EE4 cert=Hmyfd2ev46gGY7NoVxA9ngrPF2zCZtzskRTzoWXbxNkzeVnGFPWmrTtILRyqCTjHR+s9dg iat-mode=1
Bridge obfs4 38.229.33.83:80 0BAC39417268B96B9F514E7F63FA6FBA1A788955 cert=VwEFpk9F/UN9JED7XpG1XOjm/O8ZCXK80oPecgWnNDZDv5pdkhq1OpbAH0wNqOT6H6BmRQ iat-mode=1
Bridge obfs4 45.145.95.6:27015 C5B7CD6946FF10C5B3E89691A7D3F2C122D2117C cert=TD7PbUO0/0k6xYHMPW3vJxICfkMZNdkRrb63Zhl5j9dW3iRGiCx0A7mPhe5T2EDzQ35+Zw iat-mode=0 Bridge obfs4 45.145.95.6:27015 C5B7CD6946FF10C5B3E89691A7D3F2C122D2117C cert=TD7PbUO0/0k6xYHMPW3vJxICfkMZNdkRrb63Zhl5j9dW3iRGiCx0A7mPhe5T2EDzQ35+Zw iat-mode=0
Bridge obfs4 51.222.13.177:80 5EDAC3B810E12B01F6FD8050D2FD3E277B289A08 cert=2uplIpLQ0q9+0qMFrK5pkaYRDOe460LL9WHBvatgkuRr/SL31wBOEupaMMJ6koRE6Ld0ew iat-mode=0 Bridge obfs4 51.222.13.177:80 5EDAC3B810E12B01F6FD8050D2FD3E277B289A08 cert=2uplIpLQ0q9+0qMFrK5pkaYRDOe460LL9WHBvatgkuRr/SL31wBOEupaMMJ6koRE6Ld0ew iat-mode=0
Bridge obfs4 85.31.186.26:443 91A6354697E6B02A386312F68D82CF86824D3606 cert=PBwr+S8JTVZo6MPdHnkTwXJPILWADLqfMGoVvhZClMq/Urndyd42BwX9YFJHZnBB3H0XCw iat-mode=0 Bridge obfs4 85.31.186.26:443 91A6354697E6B02A386312F68D82CF86824D3606 cert=PBwr+S8JTVZo6MPdHnkTwXJPILWADLqfMGoVvhZClMq/Urndyd42BwX9YFJHZnBB3H0XCw iat-mode=0
Bridge obfs4 85.31.186.98:443 011F2599C0E9B27EE74B353155E244813763C3E5 cert=ayq0XzCwhpdysn5o0EyDUbmSOx3X/oTEbzDMvczHOdBJKlvIdHHLJGkZARtT4dcBFArPPg iat-mode=0 Bridge obfs4 85.31.186.98:443 011F2599C0E9B27EE74B353155E244813763C3E5 cert=ayq0XzCwhpdysn5o0EyDUbmSOx3X/oTEbzDMvczHOdBJKlvIdHHLJGkZARtT4dcBFArPPg iat-mode=0
Bridge obfs4 [2a0c:4d80:42:702::1]:27015 C5B7CD6946FF10C5B3E89691A7D3F2C122D2117C cert=TD7PbUO0/0k6xYHMPW3vJxICfkMZNdkRrb63Zhl5j9dW3iRGiCx0A7mPhe5T2EDzQ35+Zw iat-mode=0

View File

@ -1,2 +1,3 @@
# Enable built-in snowflake bridge # Enable built-in snowflake bridge
Bridge snowflake 192.0.2.3:1 2B280B23E1107BB62ABFC40DDCC8824814F80A72 Bridge snowflake 192.0.2.3:80 2B280B23E1107BB62ABFC40DDCC8824814F80A72 fingerprint=2B280B23E1107BB62ABFC40DDCC8824814F80A72 url=https://snowflake-broker.torproject.net.global.prod.fastly.net/ front=cdn.sstatic.net ice=stun:stun.l.google.com:19302,stun:stun.antisip.com:3478,stun:stun.bluesip.net:3478,stun:stun.dus.net:3478,stun:stun.epygi.com:3478,stun:stun.sonetel.com:3478,stun:stun.uls.co.za:3478,stun:stun.voipgate.com:3478,stun:stun.voys.nl:3478 utls-imitate=hellorandomizedalpn
Bridge snowflake 192.0.2.4:80 8838024498816A039FCBBAB14E6F40A0843051FA fingerprint=8838024498816A039FCBBAB14E6F40A0843051FA url=https://snowflake-broker.torproject.net.global.prod.fastly.net/ front=cdn.sstatic.net ice=stun:stun.l.google.com:19302,stun:stun.antisip.com:3478,stun:stun.bluesip.net:3478,stun:stun.dus.net:3478,stun:stun.epygi.com:3478,stun:stun.sonetel.net:3478,stun:stun.uls.co.za:3478,stun:stun.voipgate.com:3478,stun:stun.voys.nl:3478 utls-imitate=hellorandomizedalpn

1605
cli/poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -16,7 +16,7 @@ classifiers = [
] ]
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = "^3.7" python = ">=3.8,<3.11"
click = "*" click = "*"
flask = "2.0.3" flask = "2.0.3"
flask-socketio = "5.3.1" flask-socketio = "5.3.1"
@ -40,5 +40,5 @@ pytest = ">=7.2.0"
onionshare-cli = 'onionshare_cli:main' onionshare-cli = 'onionshare_cli:main'
[build-system] [build-system]
requires = ["poetry>=0.12"] requires = ["poetry-core"]
build-backend = "poetry.masonry.api" build-backend = "poetry.core.masonry.api"

View File

@ -151,7 +151,7 @@ class TestGetPlatform:
class TestGetTorPaths: class TestGetTorPaths:
@pytest.mark.skipif(sys.platform != "Darwin", reason="requires MacOS") @pytest.mark.skipif(sys.platform != "darwin", reason="requires MacOS")
def test_get_tor_paths_darwin( def test_get_tor_paths_darwin(
self, platform_darwin, common_obj, sys_frozen, sys_meipass self, platform_darwin, common_obj, sys_frozen, sys_meipass
): ):

View File

@ -120,7 +120,7 @@ class TestSettings:
settings_obj.set("socks_port", "NON_INTEGER") settings_obj.set("socks_port", "NON_INTEGER")
assert settings_obj._settings["socks_port"] == 9050 assert settings_obj._settings["socks_port"] == 9050
@pytest.mark.skipif(sys.platform != "Darwin", reason="requires Darwin") @pytest.mark.skipif(sys.platform != "darwin", reason="requires Darwin")
def test_filename_darwin(self, monkeypatch, platform_darwin): def test_filename_darwin(self, monkeypatch, platform_darwin):
obj = settings.Settings(common.Common()) obj = settings.Settings(common.Common())
assert obj.filename == os.path.expanduser( assert obj.filename == os.path.expanduser(

View File

@ -9,7 +9,7 @@ git clone https://github.com/onionshare/onionshare.git
cd onionshare/desktop cd onionshare/desktop
``` ```
Make sure you have Python 3 installed. If you're using Windows or macOS, install version 3.9.13 [from python.org](https://www.python.org/downloads/release/python-3913/). For Windows, make sure to check the box to add python to the path on the first page of the installer. Make sure you have Python 3 installed. If you're using Windows or macOS, install the latest version of 3.10 [from python.org](https://www.python.org/downloads/). For Windows, make sure to check the box to add python to the path on the first page of the installer.
Make sure you have [poetry](https://python-poetry.org/) installed: Make sure you have [poetry](https://python-poetry.org/) installed:
@ -29,9 +29,9 @@ poetry install
**Linux users:** In Ubuntu 20.04 you need the `libxcb-xinerama0` package installed. **Linux users:** In Ubuntu 20.04 you need the `libxcb-xinerama0` package installed.
**Windows users:** Download and install 7-Zip from https://7-zip.org/download.html. [Add](https://medium.com/@kevinmarkvi/how-to-add-executables-to-your-path-in-windows-5ffa4ce61a53) `C:\Program Files (x86)\7-Zip` to your path. **Windows users:** Download and install 7-Zip (x64) from https://7-zip.org/download.html. [Add](https://medium.com/@kevinmarkvi/how-to-add-executables-to-your-path-in-windows-5ffa4ce61a53) `C:\Program Files\7-Zip` to your path.
Download Tor Browser and extract the binaries for your platform. The platform must be `win32`, `win64`, `macos`, or `linux64`. Download Tor Browser and extract the binaries for your platform. The platform must be `win64`, `macos`, or `linux64`.
```sh ```sh
poetry run python ./scripts/get-tor.py [platform] poetry run python ./scripts/get-tor.py [platform]

View File

@ -26,10 +26,10 @@ import signal
import json import json
import psutil import psutil
import getpass import getpass
from PySide2 import QtCore, QtWidgets, QtGui from PySide6 import QtCore, QtWidgets, QtGui
from PySide2.QtCore import Slot, Qt from PySide6.QtCore import Slot, Qt
from PySide2.QtGui import QPalette, QColor from PySide6.QtGui import QPalette, QColor
from onionshare_cli.common import Common from onionshare_cli.common import Common
from onionshare_cli.settings import Settings from onionshare_cli.settings import Settings
@ -47,7 +47,6 @@ class Application(QtWidgets.QApplication):
def __init__(self, common): def __init__(self, common):
if common.platform == "Linux" or common.platform == "BSD": if common.platform == "Linux" or common.platform == "BSD":
self.setAttribute(QtCore.Qt.AA_X11InitThreads, True)
self.setDesktopFileName("org.onionshare.OnionShare") self.setDesktopFileName("org.onionshare.OnionShare")
self.setOrganizationDomain("org.onionshare.OnionShare") self.setOrganizationDomain("org.onionshare.OnionShare")
self.setOrganizationName("OnionShare") self.setOrganizationName("OnionShare")
@ -267,4 +266,4 @@ def main():
qtapp.aboutToQuit.connect(shutdown) qtapp.aboutToQuit.connect(shutdown)
# All done # All done
sys.exit(qtapp.exec_()) sys.exit(qtapp.exec())

View File

@ -20,7 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import json import json
import os import os
from PySide2 import QtCore, QtWidgets, QtGui from PySide6 import QtCore, QtWidgets, QtGui
from onionshare_cli.censorship import ( from onionshare_cli.censorship import (
CensorshipCircumvention, CensorshipCircumvention,

View File

@ -21,7 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import os import os
import shutil import shutil
from pkg_resources import resource_filename from pkg_resources import resource_filename
from PySide2 import QtCore, QtWidgets, QtGui from PySide6 import QtCore, QtWidgets, QtGui
from . import strings from . import strings
from onionshare_cli.onion import ( from onionshare_cli.onion import (
@ -602,7 +602,7 @@ class ToggleCheckbox(QtWidgets.QCheckBox):
painter.setRenderHint(QtGui.QPainter.Antialiasing) painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setPen(QtCore.Qt.NoPen) painter.setPen(QtCore.Qt.NoPen)
opt = QtWidgets.QStyleOptionButton() opt = QtWidgets.QStyleOptionButton()
opt.init(self) opt.initFrom(self)
self.initStyleOption(opt) self.initStyleOption(opt)
s = self.style() s = self.style()
s.drawControl(QtWidgets.QStyle.CE_CheckBox, opt, painter, self) s.drawControl(QtWidgets.QStyle.CE_CheckBox, opt, painter, self)

View File

@ -20,7 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import os import os
import time import time
from PySide2 import QtCore, QtWidgets, QtGui from PySide6 import QtCore, QtWidgets, QtGui
from . import strings from . import strings
from .widgets import Alert from .widgets import Alert
@ -119,7 +119,7 @@ class MainWindow(QtWidgets.QMainWindow):
) )
) )
) )
sequence = QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_H) sequence = QtGui.QKeySequence(QtCore.Qt.CTRL | QtCore.Qt.Key_H)
self.settings_button.setShortcut(sequence) self.settings_button.setShortcut(sequence)
self.settings_button.setAccessibleName(strings._("gui_settings_window_title")) self.settings_button.setAccessibleName(strings._("gui_settings_window_title"))
self.settings_button.clicked.connect(self.open_settings) self.settings_button.clicked.connect(self.open_settings)
@ -191,7 +191,7 @@ class MainWindow(QtWidgets.QMainWindow):
a.addButton(settings_button, QtWidgets.QMessageBox.AcceptRole) a.addButton(settings_button, QtWidgets.QMessageBox.AcceptRole)
a.addButton(quit_button, QtWidgets.QMessageBox.RejectRole) a.addButton(quit_button, QtWidgets.QMessageBox.RejectRole)
a.setDefaultButton(settings_button) a.setDefaultButton(settings_button)
a.exec_() a.exec()
if a.clickedButton() == settings_button: if a.clickedButton() == settings_button:
# Open settings # Open settings
@ -255,7 +255,7 @@ class MainWindow(QtWidgets.QMainWindow):
if self.tabs.are_tabs_active(): if self.tabs.are_tabs_active():
# Open the warning dialog # Open the warning dialog
self.common.log("MainWindow", "closeEvent, opening warning dialog") self.common.log("MainWindow", "closeEvent, opening warning dialog")
self.close_dialog.exec_() self.close_dialog.exec()
# Close # Close
if self.close_dialog.clickedButton() == self.close_dialog.accept_button: if self.close_dialog.clickedButton() == self.close_dialog.accept_button:
@ -303,7 +303,7 @@ class MainWindow(QtWidgets.QMainWindow):
self.onion_cleanup_thread.finished.connect(alert.accept) self.onion_cleanup_thread.finished.connect(alert.accept)
self.onion_cleanup_thread.start() self.onion_cleanup_thread.start()
alert.exec_() alert.exec()
if alert.clickedButton() == quit_early_button: if alert.clickedButton() == quit_early_button:
self.common.log("MainWindow", "cleanup", "quitting early") self.common.log("MainWindow", "cleanup", "quitting early")
if self.onion_cleanup_thread.isRunning(): if self.onion_cleanup_thread.isRunning():

View File

@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
from PySide2 import QtCore, QtWidgets, QtGui from PySide6 import QtCore, QtWidgets, QtGui
import requests import requests
import os import os
import base64 import base64

View File

@ -1,4 +1,4 @@
from PySide2 import QtCore, QtWidgets, QtGui from PySide6 import QtCore, QtWidgets, QtGui
from onionshare_cli.mode_settings import ModeSettings from onionshare_cli.mode_settings import ModeSettings

View File

@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
from PySide2 import QtCore, QtWidgets, QtGui from PySide6 import QtCore, QtWidgets, QtGui
import platform import platform
import datetime import datetime
from onionshare_cli.settings import Settings from onionshare_cli.settings import Settings

View File

@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
from PySide2 import QtCore, QtWidgets from PySide6 import QtCore, QtWidgets
from onionshare_cli.common import AutoStopTimer from onionshare_cli.common import AutoStopTimer

View File

@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
from PySide2 import QtCore, QtWidgets, QtGui from PySide6 import QtCore, QtWidgets, QtGui
from onionshare_cli.web import Web from onionshare_cli.web import Web

View File

@ -19,7 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
import os import os
from PySide2 import QtCore, QtWidgets, QtGui from PySide6 import QtCore, QtWidgets, QtGui
from ... import strings from ... import strings
from ...widgets import Alert, AddFileDialog from ...widgets import Alert, AddFileDialog
@ -434,7 +434,7 @@ class FileSelection(QtWidgets.QVBoxLayout):
Add button clicked. Add button clicked.
""" """
file_dialog = AddFileDialog(self.common, caption=strings._("gui_choose_items")) file_dialog = AddFileDialog(self.common, caption=strings._("gui_choose_items"))
if file_dialog.exec_() == QtWidgets.QDialog.Accepted: if file_dialog.exec() == QtWidgets.QDialog.Accepted:
self.common.log("FileSelection", "add", file_dialog.selectedFiles()) self.common.log("FileSelection", "add", file_dialog.selectedFiles())
for filename in file_dialog.selectedFiles(): for filename in file_dialog.selectedFiles():
self.file_list.add_file(filename) self.file_list.add_file(filename)

View File

@ -22,7 +22,7 @@ import time
import subprocess import subprocess
import os import os
from datetime import datetime from datetime import datetime
from PySide2 import QtCore, QtWidgets, QtGui from PySide6 import QtCore, QtWidgets, QtGui
from ... import strings from ... import strings
from ...widgets import Alert from ...widgets import Alert

View File

@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
from PySide2 import QtCore, QtWidgets from PySide6 import QtCore, QtWidgets
from ... import strings from ... import strings

View File

@ -19,7 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
import os import os
from PySide2 import QtCore, QtWidgets, QtGui from PySide6 import QtCore, QtWidgets, QtGui
from onionshare_cli.web import Web from onionshare_cli.web import Web

View File

@ -19,7 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
import os import os
from PySide2 import QtCore, QtWidgets, QtGui from PySide6 import QtCore, QtWidgets, QtGui
from onionshare_cli.common import Common from onionshare_cli.common import Common
from onionshare_cli.web import Web from onionshare_cli.web import Web

View File

@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
from PySide2 import QtCore from PySide6 import QtCore
class CompressThread(QtCore.QThread): class CompressThread(QtCore.QThread):

View File

@ -20,7 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import os import os
from PySide2 import QtCore, QtWidgets, QtGui from PySide6 import QtCore, QtWidgets, QtGui
from onionshare_cli.common import Common from onionshare_cli.common import Common
from onionshare_cli.web import Web from onionshare_cli.web import Web

View File

@ -18,8 +18,8 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
import textwrap import textwrap
from PySide2 import QtCore, QtWidgets, QtGui from PySide6 import QtCore, QtWidgets, QtGui
from PySide2.QtCore import Qt from PySide6.QtCore import Qt
from .. import strings from .. import strings
from ..widgets import Alert from ..widgets import Alert

View File

@ -19,7 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
import queue import queue
from PySide2 import QtCore, QtWidgets, QtGui from PySide6 import QtCore, QtWidgets, QtGui
from onionshare_cli.onionshare import OnionShare from onionshare_cli.onionshare import OnionShare
from onionshare_cli.web import Web from onionshare_cli.web import Web
@ -45,7 +45,7 @@ class NewTabButton(QtWidgets.QPushButton):
self.setFixedSize(280, 280) self.setFixedSize(280, 280)
# Keyboard shortcut, using the first letter of the mode # Keyboard shortcut, using the first letter of the mode
sequence = QtGui.QKeySequence(QtCore.Qt.CTRL + shortcut) sequence = QtGui.QKeySequence(QtCore.Qt.CTRL | shortcut)
self.setShortcut(sequence) self.setShortcut(sequence)
self.setAccessibleName(title) self.setAccessibleName(title)
@ -652,7 +652,7 @@ class Tab(QtWidgets.QWidget):
# Open the warning dialog # Open the warning dialog
self.common.log("Tab", "close_tab, opening warning dialog") self.common.log("Tab", "close_tab, opening warning dialog")
self.close_dialog.setText(dialog_text) self.close_dialog.setText(dialog_text)
self.close_dialog.exec_() self.close_dialog.exec()
# Close # Close
if self.close_dialog.clickedButton() == self.close_dialog.accept_button: if self.close_dialog.clickedButton() == self.close_dialog.accept_button:

View File

@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
from PySide2 import QtCore, QtWidgets, QtGui from PySide6 import QtCore, QtWidgets, QtGui
from onionshare_cli.mode_settings import ModeSettings from onionshare_cli.mode_settings import ModeSettings
@ -55,7 +55,7 @@ class TabWidget(QtWidgets.QTabWidget):
# Define the new tab button # Define the new tab button
self.new_tab_button = QtWidgets.QPushButton("+", parent=self) self.new_tab_button = QtWidgets.QPushButton("+", parent=self)
self.new_tab_button.setShortcut(QtCore.Qt.CTRL + QtCore.Qt.Key_T) self.new_tab_button.setShortcut(QtCore.Qt.CTRL | QtCore.Qt.Key_T)
self.new_tab_button.setFlat(True) self.new_tab_button.setFlat(True)
self.new_tab_button.setFixedSize(40, 30) self.new_tab_button.setFixedSize(40, 30)
self.new_tab_button.clicked.connect(self.new_tab_clicked) self.new_tab_button.clicked.connect(self.new_tab_clicked)
@ -196,8 +196,8 @@ class TabWidget(QtWidgets.QTabWidget):
index = self.addTab(tab, strings._("gui_new_tab")) index = self.addTab(tab, strings._("gui_new_tab"))
self.setCurrentIndex(index) self.setCurrentIndex(index)
sequence = QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_X) sequence = QtGui.QKeySequence(QtCore.Qt.CTRL | QtCore.Qt.Key_X)
close_shortcut = QtWidgets.QShortcut(sequence, tab) close_shortcut = QtGui.QShortcut(sequence, tab)
close_shortcut.activated.connect(lambda: self.close_tab(index)) close_shortcut.activated.connect(lambda: self.close_tab(index))
tab.init(mode_settings) tab.init(mode_settings)
@ -249,8 +249,8 @@ class TabWidget(QtWidgets.QTabWidget):
from_autoconnect=from_autoconnect, from_autoconnect=from_autoconnect,
) )
settings_tab.close_this_tab.connect(self.close_settings_tab) settings_tab.close_this_tab.connect(self.close_settings_tab)
sequence = QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_X) sequence = QtGui.QKeySequence(QtCore.Qt.CTRL | QtCore.Qt.Key_X)
close_shortcut = QtWidgets.QShortcut(sequence, settings_tab) close_shortcut = QtGui.QShortcut(sequence, settings_tab)
close_shortcut.activated.connect(self.close_settings_tab) close_shortcut.activated.connect(self.close_settings_tab)
self.tor_settings_tab = settings_tab.tor_settings_tab self.tor_settings_tab = settings_tab.tor_settings_tab
self.tor_settings_tab.tor_is_connected.connect(self.tor_is_connected) self.tor_settings_tab.tor_is_connected.connect(self.tor_is_connected)

View File

@ -21,7 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import time import time
import json import json
import os import os
from PySide2 import QtCore from PySide6 import QtCore
from onionshare_cli.onion import ( from onionshare_cli.onion import (
TorErrorInvalidSetting, TorErrorInvalidSetting,

View File

@ -19,7 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
import time import time
from PySide2 import QtCore, QtWidgets from PySide6 import QtCore, QtWidgets
from onionshare_cli.onion import ( from onionshare_cli.onion import (
BundledTorCanceled, BundledTorCanceled,

View File

@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
from PySide2 import QtCore, QtWidgets, QtGui from PySide6 import QtCore, QtWidgets, QtGui
import sys import sys
import platform import platform
import os import os
@ -579,7 +579,7 @@ class TorSettingsTab(QtWidgets.QWidget):
moat_dialog = MoatDialog(self.common, self.meek) moat_dialog = MoatDialog(self.common, self.meek)
moat_dialog.got_bridges.connect(self.bridge_moat_got_bridges) moat_dialog.got_bridges.connect(self.bridge_moat_got_bridges)
moat_dialog.exec_() moat_dialog.exec()
def bridge_moat_got_bridges(self, bridges): def bridge_moat_got_bridges(self, bridges):
""" """

View File

@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
from PySide2 import QtCore from PySide6 import QtCore
import datetime import datetime
import re import re
import socks import socks

View File

@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
from PySide2 import QtCore, QtWidgets, QtGui from PySide6 import QtCore, QtWidgets, QtGui
import qrcode import qrcode
from . import strings from . import strings
@ -52,7 +52,7 @@ class Alert(QtWidgets.QMessageBox):
self.setStandardButtons(buttons) self.setStandardButtons(buttons)
if autostart: if autostart:
self.exec_() self.exec()
class AddFileDialog(QtWidgets.QFileDialog): class AddFileDialog(QtWidgets.QFileDialog):
@ -71,10 +71,10 @@ class AddFileDialog(QtWidgets.QFileDialog):
self.common = common self.common = common
self.common.log("AddFileDialog", "__init__") self.common.log("AddFileDialog", "__init__")
self.setOption(self.DontUseNativeDialog, True) self.setOption(self.Option.DontUseNativeDialog, True)
self.setOption(self.ReadOnly, True) self.setOption(self.Option.ReadOnly, True)
self.setOption(self.ShowDirsOnly, False) self.setOption(self.Option.ShowDirsOnly, False)
self.setFileMode(self.ExistingFiles) self.setFileMode(self.FileMode.ExistingFiles)
tree_view = self.findChild(QtWidgets.QTreeView) tree_view = self.findChild(QtWidgets.QTreeView)
tree_view.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection) tree_view.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
list_view = self.findChild(QtWidgets.QListView, "listView") list_view = self.findChild(QtWidgets.QListView, "listView")
@ -101,7 +101,7 @@ class Image(qrcode.image.base.BaseImage):
A custom Image class, for use with the QR Code pixmap. A custom Image class, for use with the QR Code pixmap.
""" """
def __init__(self, border, width, box_size): def __init__(self, border, width, box_size, *args, **kwargs):
self.border = border self.border = border
self.width = width self.width = width
self.box_size = box_size self.box_size = box_size
@ -153,4 +153,4 @@ class QRCodeDialog(QtWidgets.QDialog):
layout.addWidget(self.qr_label_title) layout.addWidget(self.qr_label_title)
layout.addWidget(self.qr_label) layout.addWidget(self.qr_label)
self.exec_() self.exec()

2361
desktop/poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -6,11 +6,12 @@ authors = ["Micah Lee <micah@micahflee.com>"]
license = "GPLv3+" license = "GPLv3+"
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = ">=3.7,<3.11" python = ">=3.8,<3.11"
onionshare_cli = {path = "../cli", develop = true} onionshare_cli = {path = "../cli", develop = true}
PySide2 = "5.15.2.1" PySide6 = "6.4.0"
qrcode = "*" qrcode = "*"
werkzeug = "~2.0.3" werkzeug = "~2.0.3"
python-gnupg = "^0.5.0"
[tool.poetry.dev-dependencies] [tool.poetry.dev-dependencies]
click = "*" click = "*"
@ -19,6 +20,7 @@ pytest = ">=7.2.0"
pytest-faulthandler = "*" pytest-faulthandler = "*"
pytest-qt = ">=4.2.0" pytest-qt = ">=4.2.0"
cx_freeze = "*" cx_freeze = "*"
importlib-metadata = "*"
[build-system] [build-system]
requires = ["poetry-core>=1.0.0"] requires = ["poetry-core>=1.0.0"]

View File

@ -63,7 +63,7 @@ def main():
@main.command() @main.command()
def cleanup_build(): def cleanup_build():
"""Delete unused PySide2 stuff to save space""" """Delete unused PySide6 stuff to save space"""
app_path = get_app_path() app_path = get_app_path()
before_size = get_size(app_path) before_size = get_size(app_path)
@ -74,24 +74,18 @@ def cleanup_build():
"QtQuickParticles", "QtQuickParticles",
"QtRemoteObjects", "QtRemoteObjects",
"Qt3DInput", "Qt3DInput",
"QtPdfWidgets",
"QtScriptTools",
"QtNetworkAuth", "QtNetworkAuth",
"QtDataVisualization", "QtDataVisualization",
"QtWebEngineCore", "QtWebEngineCore",
"Qt3DQuickRender", "Qt3DQuickRender",
"Qt3DQuickExtras", "Qt3DQuickExtras",
"QtQuick3DRender",
"QtDesigner", "QtDesigner",
"QtNfc", "QtNfc",
"QtQuick3DAssetImport", "QtQuick3DAssetImport",
"QtBodymovin",
"QtWebEngineWidgets", "QtWebEngineWidgets",
"QtQuickWidgets", "QtQuickWidgets",
"Qt3DQuickInput", "Qt3DQuickInput",
"Qt3DQuickScene2D", "Qt3DQuickScene2D",
"QtUiPlugin",
"QtPdf",
"Qt3DRender", "Qt3DRender",
"QtQuick3DRuntimeRender", "QtQuick3DRuntimeRender",
"QtHelp", "QtHelp",
@ -100,13 +94,10 @@ def cleanup_build():
"QtWebSockets", "QtWebSockets",
"QtQuick3DUtils", "QtQuick3DUtils",
"QtQuickTemplates2", "QtQuickTemplates2",
"QtScript",
"QtPositioningQuick", "QtPositioningQuick",
"Qt3DCore", "Qt3DCore",
"QtLocation",
"QtXml", "QtXml",
"QtSerialPort", "QtSerialPort",
"QtWebView",
"QtQuick", "QtQuick",
"QtScxml", "QtScxml",
"QtQml", "QtQml",
@ -115,9 +106,7 @@ def cleanup_build():
"QtMultimedia", "QtMultimedia",
"QtQmlWorkerScript", "QtQmlWorkerScript",
"QtVirtualKeyboard", "QtVirtualKeyboard",
"QtPurchasing",
"QtOpenGL", "QtOpenGL",
"QtWebEngine",
"Qt3DQuick", "Qt3DQuick",
"QtTest", "QtTest",
"QtPositioning", "QtPositioning",
@ -127,7 +116,6 @@ def cleanup_build():
"QtQuickShapes", "QtQuickShapes",
"QtQuickTest", "QtQuickTest",
"QtNetwork", "QtNetwork",
"QtXmlPatterns",
"QtSvg", "QtSvg",
"QtDesignerComponents", "QtDesignerComponents",
"QtMultimediaWidgets", "QtMultimediaWidgets",
@ -135,27 +123,58 @@ def cleanup_build():
"Qt3DQuickAnimation", "Qt3DQuickAnimation",
"QtSensors", "QtSensors",
"Qt3DAnimation", "Qt3DAnimation",
"QtRepParser",
"QtTextToSpeech",
"QtGamepad",
"QtSerialBus",
"QtSql", "QtSql",
"QtConcurrent" "QtConcurrent",
"QtChartsQml",
"QtDataVisualizationQml",
"QtLabsAnimation",
"QtLabsFolderListModel",
"QtLabsQmlModels",
"QtLabsSettings",
"QtLabsSharedImage",
"QtLabsWavefrontMesh",
"QtOpenGLWidgets",
"QtQmlCore",
"QtQmlLocalStorage",
"QtQmlXmlListModel",
"QtQuick3DAssetUtils",
"QtQuick3DEffects",
"QtQuick3DGlslParser",
"QtQuick3DHelpers",
"QtQuick3DIblBaker",
"QtQuick3DParticleEffects",
"QtQuick3DParticles",
"QtQuickControls2Impl",
"QtQuickDialogs2",
"QtQuickDialogs2QuickImpl",
"QtQuickDialogs2Utils",
"QtQuickLayouts",
"QtQuickTimeline",
"QtRemoteObjectsQml",
"QtScxmlQml",
"QtSensorsQuick",
"QtShaderTools",
"QtStateMachine",
"QtStateMachineQml",
"QtSvgWidgets",
"QtUiTools",
"QtWebEngineQuick",
"QtWebEngineQuickDelegatesQml"
]: ]:
shutil.rmtree( shutil.rmtree(
f"{app_path}/Contents/MacOS/lib/PySide2/Qt/lib/{framework}.framework" f"{app_path}/Contents/MacOS/lib/PySide6/Qt/lib/{framework}.framework"
) )
print( print(
f"Deleted: {app_path}/Contents/MacOS/lib/PySide2/Qt/lib/{framework}.framework" f"Deleted: {app_path}/Contents/MacOS/lib/PySide6/Qt/lib/{framework}.framework"
) )
try: try:
os.remove(f"{app_path}/Contents/MacOS/lib/PySide2/{framework}.abi3.so") os.remove(f"{app_path}/Contents/MacOS/lib/PySide6/{framework}.abi3.so")
print(f"Deleted: {app_path}/Contents/MacOS/lib/PySide2/{framework}.abi3.so") print(f"Deleted: {app_path}/Contents/MacOS/lib/PySide6/{framework}.abi3.so")
except FileNotFoundError: except FileNotFoundError:
pass pass
try: try:
os.remove(f"{app_path}/Contents/MacOS/lib/PySide2/{framework}.pyi") os.remove(f"{app_path}/Contents/MacOS/lib/PySide6/{framework}.pyi")
print(f"Deleted: {app_path}/Contents/MacOS/lib/PySide2/{framework}.pyi") print(f"Deleted: {app_path}/Contents/MacOS/lib/PySide6/{framework}.pyi")
except FileNotFoundError: except FileNotFoundError:
pass pass
@ -176,28 +195,31 @@ def cleanup_build():
# Move frameworks from Resources/lib into Frameworks # Move frameworks from Resources/lib into Frameworks
os.makedirs(f"{app_path}/Contents/Frameworks", exist_ok=True) os.makedirs(f"{app_path}/Contents/Frameworks", exist_ok=True)
for framework_filename in glob.glob( for framework_filename in glob.glob(
f"{app_path}/Contents/Resources/lib/PySide2/Qt/lib/Qt*.framework" f"{app_path}/Contents/Resources/lib/PySide6/Qt/lib/Qt*.framework"
): ):
basename = os.path.basename(framework_filename) basename = os.path.basename(framework_filename)
os.rename(framework_filename, f"{app_path}/Contents/Frameworks/{basename}") os.rename(framework_filename, f"{app_path}/Contents/Frameworks/{basename}")
run( run(
["ln", "-s", f"../../../../../Frameworks/{basename}"], ["ln", "-s", f"../../../../../Frameworks/{basename}"],
cwd=f"{app_path}/Contents/Resources/lib/PySide2/Qt/lib", cwd=f"{app_path}/Contents/Resources/lib/PySide6/Qt/lib",
) )
if os.path.exists(f"{app_path}/Contents/Frameworks/{basename}/Resources"): if os.path.exists(f"{app_path}/Contents/Frameworks/{basename}/Resources"):
if not os.path.exists(f"{app_path}/Contents/Frameworks/{basename}/Versions/A/Resources"):
os.rename( os.rename(
f"{app_path}/Contents/Frameworks/{basename}/Resources", f"{app_path}/Contents/Frameworks/{basename}/Resources",
f"{app_path}/Contents/Frameworks/{basename}/Versions/5/Resources", f"{app_path}/Contents/Frameworks/{basename}/Versions/A/Resources",
) )
else:
shutil.rmtree(f"{app_path}/Contents/Frameworks/{basename}/Resources")
run( run(
["ln", "-s", "Versions/5/Resources"], ["ln", "-s", "Versions/A/Resources"],
cwd=f"{app_path}/Contents/Frameworks/{basename}", cwd=f"{app_path}/Contents/Frameworks/{basename}",
) )
try: try:
run( run(
["ln", "-s", "5", "Current"], ["ln", "-s", "A", "Current"],
cwd=f"{app_path}/Contents/Frameworks/{basename}/Versions", cwd=f"{app_path}/Contents/Frameworks/{basename}/Versions",
) )
except: except:
@ -205,27 +227,49 @@ def cleanup_build():
# Move Qt plugins # Move Qt plugins
os.rename( os.rename(
f"{app_path}/Contents/Resources/lib/PySide2/Qt/plugins", f"{app_path}/Contents/Resources/lib/PySide6/Qt/plugins",
f"{app_path}/Contents/Frameworks/plugins", f"{app_path}/Contents/Frameworks/plugins",
) )
run( run(
["ln", "-s", "../../../../Frameworks/plugins"], ["ln", "-s", "../../../../Frameworks/plugins"],
cwd=f"{app_path}/Contents/Resources/lib/PySide2/Qt", cwd=f"{app_path}/Contents/Resources/lib/PySide6/Qt",
) )
print("> Delete more unused PySide2 stuff to save space") print("> Delete more unused PySide6 stuff to save space")
for filename in [ for filename in [
f"{app_path}/Contents/Resources/lib/PySide2/Designer.app", f"{app_path}/Contents/Resources/lib/PySide6/Designer.app",
f"{app_path}/Contents/Resources/lib/PySide2/examples", f"{app_path}/Contents/Resources/lib/PySide6/examples",
f"{app_path}/Contents/Resources/lib/PySide2/glue", f"{app_path}/Contents/Resources/lib/PySide6/glue",
f"{app_path}/Contents/Resources/lib/PySide2/include", f"{app_path}/Contents/Resources/lib/PySide6/include",
f"{app_path}/Contents/Resources/lib/PySide2/pyside2-lupdate", f"{app_path}/Contents/Resources/lib/PySide6/lupdate",
f"{app_path}/Contents/Resources/lib/PySide2/rcc", f"{app_path}/Contents/Resources/lib/PySide6/libpyside6.abi3.6.4.dylib",
f"{app_path}/Contents/Resources/lib/PySide2/uic", f"{app_path}/Contents/Resources/lib/PySide6/Qt/qml",
f"{app_path}/Contents/Resources/lib/PySide2/libpyside2.abi3.5.15.dylib", f"{app_path}/Contents/Resources/lib/shiboken6/libshiboken6.abi3.6.4.dylib",
f"{app_path}/Contents/Resources/lib/PySide2/Qt/qml", f"{app_path}/Contents/Resources/lib/PySide6/Assistant.app",
f"{app_path}/Contents/Resources/lib/shiboken2/libshiboken2.abi3.5.15.dylib", f"{app_path}/Contents/Resources/lib/PySide6/Linguist.app",
f"{app_path}/Contents/Resources/lib/shiboken2/docs", f"{app_path}/Contents/Resources/lib/PySide6/libpyside6qml.abi3.6.4.dylib",
f"{app_path}/Contents/Resources/lib/PySide6/lrelease",
f"{app_path}/Contents/Resources/lib/PySide6/qmlformat",
f"{app_path}/Contents/Resources/lib/PySide6/qmllint",
f"{app_path}/Contents/Resources/lib/PySide6/qmlls",
f"{app_path}/Contents/MacOS/QtBluetooth",
f"{app_path}/Contents/MacOS/QtConcurrent",
f"{app_path}/Contents/MacOS/QtDesigner",
f"{app_path}/Contents/MacOS/QtNetworkAuth",
f"{app_path}/Contents/MacOS/QtNfc",
f"{app_path}/Contents/MacOS/QtOpenGL",
f"{app_path}/Contents/MacOS/QtOpenGLWidgets",
f"{app_path}/Contents/MacOS/QtPositioning",
f"{app_path}/Contents/MacOS/QtQuick3D",
f"{app_path}/Contents/MacOS/QtQuick3DRuntimeRender",
f"{app_path}/Contents/MacOS/QtQuick3DUtils",
f"{app_path}/Contents/MacOS/QtShaderTools",
f"{app_path}/Contents/MacOS/QtStateMachine",
f"{app_path}/Contents/MacOS/QtSvgWidgets",
f"{app_path}/Contents/MacOS/QtWebChannel",
f"{app_path}/Contents/MacOS/QtWebEngineCore",
f"{app_path}/Contents/MacOS/QtWebEngineQuick",
f"{app_path}/Contents/MacOS/QtXml",
]: ]:
if os.path.isfile(filename) or os.path.islink(filename): if os.path.isfile(filename) or os.path.islink(filename):
os.remove(filename) os.remove(filename)
@ -250,11 +294,10 @@ def codesign(app_path):
glob.glob(f"{app_path}/Contents/Resources/lib/**/*.so", recursive=True), glob.glob(f"{app_path}/Contents/Resources/lib/**/*.so", recursive=True),
glob.glob(f"{app_path}/Contents/Resources/lib/**/*.dylib", recursive=True), glob.glob(f"{app_path}/Contents/Resources/lib/**/*.dylib", recursive=True),
[ [
f"{app_path}/Contents/Frameworks/QtCore.framework/Versions/5/QtCore", f"{app_path}/Contents/Frameworks/QtCore.framework/Versions/A/QtCore",
f"{app_path}/Contents/Frameworks/QtDBus.framework/Versions/5/QtDBus", f"{app_path}/Contents/Frameworks/QtDBus.framework/Versions/A/QtDBus",
f"{app_path}/Contents/Frameworks/QtGui.framework/Versions/5/QtGui", f"{app_path}/Contents/Frameworks/QtGui.framework/Versions/A/QtGui",
f"{app_path}/Contents/Frameworks/QtMacExtras.framework/Versions/5/QtMacExtras", f"{app_path}/Contents/Frameworks/QtWidgets.framework/Versions/A/QtWidgets",
f"{app_path}/Contents/Frameworks/QtWidgets.framework/Versions/5/QtWidgets",
f"{app_path}/Contents/Resources/lib/Python", f"{app_path}/Contents/Resources/lib/Python",
f"{app_path}/Contents/Resources/lib/onionshare/resources/tor/meek-client", f"{app_path}/Contents/Resources/lib/onionshare/resources/tor/meek-client",
f"{app_path}/Contents/Resources/lib/onionshare/resources/tor/obfs4proxy", f"{app_path}/Contents/Resources/lib/onionshare/resources/tor/obfs4proxy",

View File

@ -1,9 +1,23 @@
#!/bin/bash #!/bin/bash
MEEK_TAG=v0.37.0 MEEK_TAG=v0.37.0
OS=$(uname -s)
mkdir -p ./build/meek mkdir -p ./build/meek
cd ./build/meek cd ./build/meek
git clone https://git.torproject.org/pluggable-transports/meek.git git clone https://git.torproject.org/pluggable-transports/meek.git || echo "already cloned"
cd meek cd meek
git checkout $MEEK_TAG git checkout $MEEK_TAG
go build -o ../../../onionshare/resources/tor/meek-client ./meek-client
if [ "$OS" == "Darwin" ]; then
if [[ $(uname -m) == 'arm64' ]]; then
go build -o ../../../onionshare/resources/tor/meek-client-arm64 ./meek-client
GOOS=darwin GOARCH=amd64 go build -o ../../../onionshare/resources/tor/meek-client-amd64 ./meek-client
lipo -create -output ../../../onionshare/resources/tor/meek-client ../../../onionshare/resources/tor/meek-client-arm64 ../../../onionshare/resources/tor/meek-client-amd64
rm ../../../onionshare/resources/tor/meek-client-arm64 ../../../onionshare/resources/tor/meek-client-amd64
elif [[ $(uname -m) == 'x86_64' ]]; then
go build -o ../../../onionshare/resources/tor/meek-client ./meek-client
fi
else
go build -o ../../../onionshare/resources/tor/meek-client ./meek-client
fi

View File

@ -1,9 +1,22 @@
#!/bin/bash #!/bin/bash
OBFS4PROXY_TAG=obfs4proxy-0.0.14 OBFS4PROXY_TAG=obfs4proxy-0.0.14
OS=$(uname -s)
mkdir -p ./build/obfs4proxy mkdir -p ./build/obfs4proxy
cd ./build/obfs4proxy cd ./build/obfs4proxy
git clone https://gitlab.com/yawning/obfs4 || echo "already cloned" git clone https://gitlab.com/yawning/obfs4 || echo "already cloned"
cd obfs4 cd obfs4
git checkout $OBFS4PROXY_TAG git checkout $OBFS4PROXY_TAG
go build -o ../../../onionshare/resources/tor/obfs4proxy ./obfs4proxy if [ "$OS" == "Darwin" ]; then
if [[ $(uname -m) == 'arm64' ]]; then
go build -o ../../../onionshare/resources/tor/obfs4proxy-arm64 ./obfs4proxy
GOOS=darwin GOARCH=amd64 go build -o ../../../onionshare/resources/tor/obfs4proxy-amd64 ./obfs4proxy
lipo -create -output ../../../onionshare/resources/tor/obfs4proxy ../../../onionshare/resources/tor/obfs4proxy-arm64 ../../../onionshare/resources/tor/obfs4proxy-amd64
rm ../../../onionshare/resources/tor/obfs4proxy-arm64 ../../../onionshare/resources/tor/obfs4proxy-amd64
elif [[ $(uname -m) == 'x86_64' ]]; then
go build -o ../../../onionshare/resources/tor/obfs4proxy ./obfs4proxy
fi
else
go build -o ../../../onionshare/resources/tor/obfs4proxy ./obfs4proxy
fi

View File

@ -1,9 +1,22 @@
#!/bin/bash #!/bin/bash
SNOWFLAKE_TAG=v2.3.1 SNOWFLAKE_TAG=v2.3.1
OS=$(uname -s)
mkdir -p ./build/snowflake mkdir -p ./build/snowflake
cd ./build/snowflake cd ./build/snowflake
git clone https://git.torproject.org/pluggable-transports/snowflake.git git clone https://git.torproject.org/pluggable-transports/snowflake.git || echo "already cloned"
cd snowflake cd snowflake
git checkout $SNOWFLAKE_TAG git checkout $SNOWFLAKE_TAG
go build -o ../../../onionshare/resources/tor/snowflake-client ./client if [ "$OS" == "Darwin" ]; then
if [[ $(uname -m) == 'arm64' ]]; then
go build -o ../../../onionshare/resources/tor/snowflake-client-arm64 ./client
GOOS=darwin GOARCH=amd64 go build -o ../../../onionshare/resources/tor/snowflake-client-amd64 ./client
lipo -create -output ../../../onionshare/resources/tor/snowflake-client ../../../onionshare/resources/tor/snowflake-client-arm64 ../../../onionshare/resources/tor/snowflake-client-amd64
rm ../../../onionshare/resources/tor/snowflake-client-arm64 ../../../onionshare/resources/tor/snowflake-client-amd64
elif [[ $(uname -m) == 'x86_64' ]]; then
go build -o ../../../onionshare/resources/tor/snowflake-client ./client
fi
else
go build -o ../../../onionshare/resources/tor/snowflake-client ./client
fi

View File

@ -8,6 +8,7 @@ import shutil
import subprocess import subprocess
import uuid import uuid
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
from glob import glob
root = os.path.dirname( root = os.path.dirname(
os.path.dirname( os.path.dirname(
@ -17,14 +18,6 @@ root = os.path.dirname(
desktop_dir = os.path.join(root, "desktop") desktop_dir = os.path.join(root, "desktop")
def get_build_path():
if "64 bit" in sys.version:
python_arch = "win-amd64"
else:
python_arch = "win32"
return os.path.join(desktop_dir, "build", f"exe.{python_arch}-3.9")
def get_size(dir): def get_size(dir):
size = 0 size = 0
for path, dirs, files in os.walk(dir): for path, dirs, files in os.walk(dir):
@ -327,244 +320,58 @@ def main():
@main.command() @main.command()
def cleanup_build(): def cleanup_build():
"""Delete unused PySide2 stuff to save space""" """Delete unused PySide6 stuff to save space"""
build_path = get_build_path() build_path = os.path.join(desktop_dir, "build", "exe.win-amd64-3.10")
before_size = get_size(build_path) before_size = get_size(build_path)
for dirname in ["examples", "qml"]: for dirname in ["examples", "qml"]:
shutil.rmtree(os.path.join(build_path, "lib", "PySide2", dirname)) shutil.rmtree(os.path.join(build_path, "lib", "PySide6", dirname))
for filename in [ for dirname in [
"lconvert.exe", "assetimporters",
"linguist.exe", "designer",
"lrelease.exe", "generic",
"lupdate.exe", "geometryloaders",
"plugins/assetimporters/assimp.dll", "platforminputcontexts",
"plugins/assetimporters/uip.dll", "position",
"plugins/audio/qtaudio_wasapi.dll", "qmltooling",
"plugins/audio/qtaudio_windows.dll", "renderers",
"plugins/bearer/qgenericbearer.dll", "renderplugins",
"plugins/canbus/qtpassthrucanbus.dll", "sceneparsers",
"plugins/canbus/qtpeakcanbus.dll", "scxmldatamodel",
"plugins/canbus/qtsysteccanbus.dll", "sensors",
"plugins/canbus/qttinycanbus.dll", "sqldrivers",
"plugins/canbus/qtvectorcanbus.dll", "styles",
"plugins/canbus/qtvirtualcanbus.dll",
"plugins/gamepads/xinputgamepad.dll",
"plugins/generic/qtuiotouchplugin.dll",
"plugins/geometryloaders/defaultgeometryloader.dll",
"plugins/geometryloaders/gltfgeometryloader.dll",
"plugins/geoservices/qtgeoservices_esri.dll",
"plugins/geoservices/qtgeoservices_itemsoverlay.dll",
"plugins/geoservices/qtgeoservices_mapbox.dll",
"plugins/geoservices/qtgeoservices_nokia.dll",
"plugins/geoservices/qtgeoservices_osm.dll",
"plugins/mediaservice/dsengine.dll",
"plugins/mediaservice/qtmedia_audioengine.dll",
"plugins/mediaservice/wmfengine.dll",
"plugins/platforminputcontexts/qtvirtualkeyboardplugin.dll",
"plugins/platforms/qdirect2d.dll",
"plugins/platforms/qoffscreen.dll",
"plugins/platforms/qwebgl.dll",
"plugins/platformthemes/qxdgdesktopportal.dll",
"plugins/playlistformats/qtmultimedia_m3u.dll",
"plugins/position/qtposition_positionpoll.dll",
"plugins/position/qtposition_serialnmea.dll",
"plugins/position/qtposition_winrt.dll",
"plugins/printsupport/windowsprintersupport.dll",
"plugins/qmltooling/qmldbg_debugger.dll",
"plugins/qmltooling/qmldbg_inspector.dll",
"plugins/qmltooling/qmldbg_local.dll",
"plugins/qmltooling/qmldbg_messages.dll",
"plugins/qmltooling/qmldbg_native.dll",
"plugins/qmltooling/qmldbg_nativedebugger.dll",
"plugins/qmltooling/qmldbg_preview.dll",
"plugins/qmltooling/qmldbg_profiler.dll",
"plugins/qmltooling/qmldbg_quickprofiler.dll",
"plugins/qmltooling/qmldbg_server.dll",
"plugins/qmltooling/qmldbg_tcp.dll",
"plugins/renderers/openglrenderer.dll",
"plugins/renderplugins/scene2d.dll",
"plugins/scenegraph/qsgd3d12backend.dll",
"plugins/sceneparsers/gltfsceneexport.dll",
"plugins/sceneparsers/gltfsceneimport.dll",
"plugins/sensorgestures/qtsensorgestures_plugin.dll",
"plugins/sensorgestures/qtsensorgestures_shakeplugin.dll",
"plugins/sensors/qtsensors_generic.dll",
"plugins/sqldrivers/qsqlite.dll",
"plugins/sqldrivers/qsqlodbc.dll",
"plugins/sqldrivers/qsqlpsql.dll",
"plugins/styles/qwindowsvistastyle.dll",
"plugins/texttospeech/qtexttospeech_sapi.dll",
"plugins/virtualkeyboard/qtvirtualkeyboard_hangul.dll",
"plugins/virtualkeyboard/qtvirtualkeyboard_openwnn.dll",
"plugins/virtualkeyboard/qtvirtualkeyboard_pinyin.dll",
"plugins/virtualkeyboard/qtvirtualkeyboard_tcime.dll",
"plugins/virtualkeyboard/qtvirtualkeyboard_thai.dll",
"plugins/webview/qtwebview_webengine.dll",
"pyside2-lupdate.exe",
"Qt3DAnimation.pyd",
"Qt3DAnimation.pyi",
"Qt3DCore.pyd",
"Qt3DCore.pyi",
"Qt3DExtras.pyd",
"Qt3DExtras.pyi",
"Qt3DInput.pyd",
"Qt3DInput.pyi",
"Qt3DLogic.pyd",
"Qt3DLogic.pyi",
"Qt3DRender.pyd",
"Qt3DRender.pyi",
"Qt53DAnimation.dll",
"Qt53DCore.dll",
"Qt53DExtras.dll",
"Qt53DInput.dll",
"Qt53DLogic.dll",
"Qt53DQuick.dll",
"Qt53DQuickAnimation.dll",
"Qt53DQuickExtras.dll",
"Qt53DQuickInput.dll",
"Qt53DQuickRender.dll",
"Qt53DQuickScene2D.dll",
"Qt53DRender.dll",
"Qt5Bluetooth.dll",
"Qt5Bodymovin.dll",
"Qt5Charts.dll",
"Qt5Concurrent.dll",
"Qt5DataVisualization.dll",
"Qt5DBus.dll",
"Qt5Designer.dll",
"Qt5DesignerComponents.dll",
"Qt5Gamepad.dll",
"Qt5Help.dll",
"Qt5Location.dll",
"Qt5Multimedia.dll",
"Qt5MultimediaQuick.dll",
"Qt5MultimediaWidgets.dll",
"Qt5Nfc.dll",
"Qt5OpenGL.dll",
"Qt5Pdf.dll",
"Qt5PdfWidgets.dll",
"Qt5Positioning.dll",
"Qt5PositioningQuick.dll",
"Qt5PrintSupport.dll",
"Qt5Purchasing.dll",
"Qt5Quick.dll",
"Qt5Quick3D.dll",
"Qt5Quick3DAssetImport.dll",
"Qt5Quick3DRender.dll",
"Qt5Quick3DRuntimeRender.dll",
"Qt5Quick3DUtils.dll",
"Qt5QuickControls2.dll",
"Qt5QuickParticles.dll",
"Qt5QuickShapes.dll",
"Qt5QuickTemplates2.dll",
"Qt5QuickTest.dll",
"Qt5QuickWidgets.dll",
"Qt5RemoteObjects.dll",
"Qt5Script.dll",
"Qt5ScriptTools.dll",
"Qt5Scxml.dll",
"Qt5Sensors.dll",
"Qt5SerialBus.dll",
"Qt5SerialPort.dll",
"Qt5Sql.dll",
"Qt5Svg.dll",
"Qt5Test.dll",
"Qt5TextToSpeech.dll",
"Qt5VirtualKeyboard.dll",
"Qt5WebChannel.dll",
"Qt5WebEngine.dll",
"Qt5WebEngineCore.dll",
"Qt5WebEngineWidgets.dll",
"Qt5WebSockets.dll",
"Qt5WebView.dll",
"Qt5Xml.dll",
"Qt5XmlPatterns.dll",
"QtAxContainer.pyd",
"QtAxContainer.pyi",
"QtCharts.pyd",
"QtCharts.pyi",
"QtConcurrent.pyd",
"QtConcurrent.pyi",
"QtDataVisualization.pyd",
"QtDataVisualization.pyi",
"qtdiag.exe",
"QtHelp.pyd",
"QtHelp.pyi",
"QtLocation.pyd",
"QtLocation.pyi",
"QtMultimedia.pyd",
"QtMultimedia.pyi",
"QtMultimediaWidgets.pyd",
"QtMultimediaWidgets.pyi",
"QtNetwork.pyd",
"QtNetwork.pyi",
"QtOpenGL.pyd",
"QtOpenGL.pyi",
"QtOpenGLFunctions.pyd",
"QtOpenGLFunctions.pyi",
"QtPositioning.pyd",
"QtPositioning.pyi",
"QtPrintSupport.pyd",
"QtPrintSupport.pyi",
"QtQml.pyd",
"QtQml.pyi",
"QtQuick.pyd",
"QtQuick.pyi",
"QtQuickControls2.pyd",
"QtQuickControls2.pyi",
"QtQuickWidgets.pyd",
"QtQuickWidgets.pyi",
"QtRemoteObjects.pyd",
"QtRemoteObjects.pyi",
"QtScript.pyd",
"QtScript.pyi",
"QtScriptTools.pyd",
"QtScriptTools.pyi",
"QtScxml.pyd",
"QtScxml.pyi",
"QtSensors.pyd",
"QtSensors.pyi",
"QtSerialPort.pyd",
"QtSerialPort.pyi",
"QtSql.pyd",
"QtSql.pyi",
"QtSvg.pyd",
"QtSvg.pyi",
"QtTest.pyd",
"QtTest.pyi",
"QtTextToSpeech.pyd",
"QtTextToSpeech.pyi",
"QtUiTools.pyd",
"QtUiTools.pyi",
"QtWebChannel.pyd",
"QtWebChannel.pyi",
"QtWebEngine.pyd",
"QtWebEngine.pyi",
"QtWebEngineCore.pyd",
"QtWebEngineCore.pyi",
"QtWebEngineProcess.exe",
"QtWebEngineWidgets.pyd",
"QtWebEngineWidgets.pyi",
"QtWebSockets.pyd",
"QtWebSockets.pyi",
"QtWinExtras.pyd",
"QtWinExtras.pyi",
"QtXml.pyd",
"QtXml.pyi",
"QtXmlPatterns.pyd",
"QtXmlPatterns.pyi",
"rcc.exe",
"uic.exe",
]: ]:
os.remove( shutil.rmtree(os.path.join(build_path, "lib", "PySide6", "plugins", dirname))
os.path.join( for filename in (
build_path, glob(os.path.join(build_path, "lib", "PySide6", "*.exe"))
"lib", + glob(os.path.join(build_path, "lib", "PySide6", "Qt3D*"))
"PySide2", + glob(os.path.join(build_path, "lib", "PySide6", "Qt63D*"))
filename.replace("/", "\\"), + glob(os.path.join(build_path, "lib", "PySide6", "Qt6Bluetooth.*"))
) + glob(os.path.join(build_path, "lib", "PySide6", "Qt6Charts*"))
) + glob(os.path.join(build_path, "lib", "PySide6", "Qt6Concurrent.*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6DataVisualization*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6Bus.dll"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6Designer*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6Help.dll"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6Labs*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6Multimedia*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6Nfc.dll"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6OpenGL*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6Qml*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6Quick*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6RemoteObjects*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6Scxml*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6Sensors*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6SerialPort.*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6ShaderTools.*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6Sql.*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6StateMachine*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6Test.*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6VirtualKeyboard.*"))
+ glob(os.path.join(build_path, "lib", "PySide6", "Qt6Web*"))
):
os.remove(filename)
after_size = get_size(build_path) after_size = get_size(build_path)
freed_bytes = before_size - after_size freed_bytes = before_size - after_size
@ -573,18 +380,13 @@ def cleanup_build():
@main.command() @main.command()
@click.argument("win32_path") @click.argument("path")
@click.argument("win64_path") def codesign(path):
def codesign(win32_path, win64_path):
"""Sign Windows binaries before packaging""" """Sign Windows binaries before packaging"""
paths = [win32_path, win64_path]
for path in paths:
if not os.path.isdir(path): if not os.path.isdir(path):
click.echo("Invalid build path") click.echo("Invalid build path")
return return
for path in paths:
sign(os.path.join(path, "onionshare.exe")) sign(os.path.join(path, "onionshare.exe"))
sign(os.path.join(path, "onionshare-cli.exe")) sign(os.path.join(path, "onionshare-cli.exe"))
sign( sign(
@ -620,9 +422,8 @@ def codesign(win32_path, win64_path):
@main.command() @main.command()
@click.argument("win32_path") @click.argument("path")
@click.argument("win64_path") def package(path):
def package(win32_path, win64_path):
"""Build the MSI package""" """Build the MSI package"""
version_filename = os.path.join( version_filename = os.path.join(
root, "cli", "onionshare_cli", "resources", "version.txt" root, "cli", "onionshare_cli", "resources", "version.txt"
@ -631,12 +432,7 @@ def package(win32_path, win64_path):
version = f.read().strip() version = f.read().strip()
msi_package( msi_package(
win32_path, path,
os.path.join(desktop_dir, "dist", f"OnionShare-win32-{version}.msi"),
"12b9695c-965b-4be0-bc33-21274e809576",
)
msi_package(
win64_path,
os.path.join(desktop_dir, "dist", f"OnionShare-win64-{version}.msi"), os.path.join(desktop_dir, "dist", f"OnionShare-win64-{version}.msi"),
"ed7f9243-3528-4b4a-b85c-9943982e75eb", "ed7f9243-3528-4b4a-b85c-9943982e75eb",
) )

View File

@ -8,30 +8,13 @@ import shutil
import subprocess import subprocess
import requests import requests
import click import click
import tempfile
import gnupg
torbrowser_version = "12.0" torbrowser_latest_url = (
expected_win32_sha256 = ( "https://aus1.torproject.org/torbrowser/update_3/release/downloads.json"
"a9cc0f0af2ce8ca0d7a27d65c7efa37f6419cfc793fa80371e7db73d44b4cc02"
) )
expected_win64_sha256 = ( tor_dev_fingerprint = "EF6E286DDA85EA2A4BA7DE684E2C6E8793298290"
"f496cc0219c8b73f1f100124d6514bad55f503ff76202747f23620a6677e83c2"
)
expected_macos_sha256 = (
"11c8360187356e6c0837612a320f1a117303fc449602c9fd73f4faf9f9bbcfc9"
)
expected_linux64_sha256 = (
"850ce601d815bac63e4f5937646d2b497173be28b27b30a7526ebb946a459874"
)
win32_filename = f"torbrowser-install-{torbrowser_version}_ALL.exe"
win32_url = f"https://dist.torproject.org/torbrowser/{torbrowser_version}/{win32_filename}"
win64_filename = f"torbrowser-install-win64-{torbrowser_version}_ALL.exe"
win64_url = f"https://dist.torproject.org/torbrowser/{torbrowser_version}/{win64_filename}"
macos_filename = f"TorBrowser-{torbrowser_version}-macos_ALL.dmg"
macos_url = f"https://dist.torproject.org/torbrowser/{torbrowser_version}/{macos_filename}"
linux64_filename = f"tor-browser-linux64-{torbrowser_version}_ALL.tar.xz"
linux64_url = f"https://dist.torproject.org/torbrowser/{torbrowser_version}/{linux64_filename}"
# Common paths # Common paths
root_path = os.path.dirname( root_path = os.path.dirname(
@ -40,27 +23,25 @@ root_path = os.path.dirname(
working_path = os.path.join(root_path, "build", "tor") working_path = os.path.join(root_path, "build", "tor")
def get_tor_windows(platform): def get_latest_tor_version_urls(platform):
if platform == "win32": r = requests.get(torbrowser_latest_url)
win_url = win32_url if r.status_code != 200 or platform not in r.json()["downloads"]:
win_filename = win32_filename print("Tor browser latest version url not working")
expected_win_sha256 = expected_win32_sha256 sys.exit(-1)
bin_filenames = [
"tor.exe" platform_url = r.json()["downloads"][platform]["ALL"]["binary"]
] platform_sig_url = r.json()["downloads"][platform]["ALL"]["sig"]
elif platform == "win64": platform_filename = platform_url.split("/")[-1]
win_url = win64_url
win_filename = win64_filename return platform_url, platform_filename, platform_sig_url
expected_win_sha256 = expected_win64_sha256
bin_filenames = [
"tor.exe" def get_tor_windows(gpg, torkey, win_url, win_filename, expected_win_sig):
] bin_filenames = ["tor.exe"]
else:
click.echo("invalid platform")
return
# Build paths # Build paths
win_path = os.path.join(working_path, win_filename) win_path = os.path.join(working_path, win_filename)
win_sig_path = os.path.join(working_path, f"{win_filename}.asc")
dist_path = os.path.join(root_path, "onionshare", "resources", "tor") dist_path = os.path.join(root_path, "onionshare", "resources", "tor")
# Make sure the working folder exists # Make sure the working folder exists
@ -72,19 +53,22 @@ def get_tor_windows(platform):
print("Downloading {}".format(win_url)) print("Downloading {}".format(win_url))
r = requests.get(win_url) r = requests.get(win_url)
open(win_path, "wb").write(r.content) open(win_path, "wb").write(r.content)
win_sha256 = hashlib.sha256(r.content).hexdigest()
else:
print("Already downloaded: {}".format(win_path))
win_data = open(win_path, "rb").read()
win_sha256 = hashlib.sha256(win_data).hexdigest()
# Compare the hash # Make sure Tor Browser signature is downloaded
if win_sha256 != expected_win_sha256: if not os.path.exists(win_sig_path):
print("ERROR! The sha256 doesn't match:") print("Downloading {}".format(expected_win_sig))
print("expected: {}".format(expected_win32_sha256)) r = requests.get(expected_win_sig)
print(" actual: {}".format(win_sha256)) open(win_sig_path, "wb").write(r.content)
# Verify the signature
sig_stream = open(win_sig_path, "rb")
verified = gpg.verify_file(sig_stream, win_path)
if not verified.valid or verified.pubkey_fingerprint != tor_dev_fingerprint:
print("ERROR! The tarball verification with the signature failed!")
sys.exit(-1) sys.exit(-1)
print("Tor Browser verification successful!")
# Extract the bits we need from the exe # Extract the bits we need from the exe
subprocess.Popen( subprocess.Popen(
[ [
@ -126,12 +110,13 @@ def get_tor_windows(platform):
update_tor_bridges() update_tor_bridges()
def get_tor_macos(): def get_tor_macos(gpg, torkey, macos_url, macos_filename, expected_macos_sig):
# Build paths # Build paths
dmg_tor_path = os.path.join( dmg_tor_path = os.path.join(
"/Volumes", "Tor Browser", "Tor Browser.app", "Contents" "/Volumes", "Tor Browser", "Tor Browser.app", "Contents"
) )
dmg_path = os.path.join(working_path, macos_filename) dmg_path = os.path.join(working_path, macos_filename)
dmg_sig_path = os.path.join(working_path, f"{macos_filename}.asc")
dist_path = os.path.join(root_path, "onionshare", "resources", "tor") dist_path = os.path.join(root_path, "onionshare", "resources", "tor")
if not os.path.exists(dist_path): if not os.path.exists(dist_path):
os.makedirs(dist_path, exist_ok=True) os.makedirs(dist_path, exist_ok=True)
@ -145,18 +130,22 @@ def get_tor_macos():
print("Downloading {}".format(macos_url)) print("Downloading {}".format(macos_url))
r = requests.get(macos_url) r = requests.get(macos_url)
open(dmg_path, "wb").write(r.content) open(dmg_path, "wb").write(r.content)
dmg_sha256 = hashlib.sha256(r.content).hexdigest()
else:
dmg_data = open(dmg_path, "rb").read()
dmg_sha256 = hashlib.sha256(dmg_data).hexdigest()
# Compare the hash # Make sure the signature is downloaded
if dmg_sha256 != expected_macos_sha256: if not os.path.exists(dmg_sig_path):
print("ERROR! The sha256 doesn't match:") print("Downloading {}".format(expected_macos_sig))
print("expected: {}".format(expected_macos_sha256)) r = requests.get(expected_macos_sig)
print(" actual: {}".format(dmg_sha256)) open(dmg_sig_path, "wb").write(r.content)
# Verify the signature
sig_stream = open(dmg_sig_path, "rb")
verified = gpg.verify_file(sig_stream, dmg_path)
if not verified.valid or verified.pubkey_fingerprint != tor_dev_fingerprint:
print("ERROR! The tarball verification with the signature failed!")
sys.exit(-1) sys.exit(-1)
print("Tor Browser verification successful!")
# Mount the dmg, copy data to the working path # Mount the dmg, copy data to the working path
subprocess.call(["hdiutil", "attach", dmg_path]) subprocess.call(["hdiutil", "attach", dmg_path])
@ -186,9 +175,10 @@ def get_tor_macos():
update_tor_bridges() update_tor_bridges()
def get_tor_linux64(): def get_tor_linux64(gpg, torkey, linux64_url, linux64_filename, expected_linux64_sig):
# Build paths # Build paths
tarball_path = os.path.join(working_path, linux64_filename) tarball_path = os.path.join(working_path, linux64_filename)
tarball_sig_path = os.path.join(working_path, f"{linux64_filename}.asc")
dist_path = os.path.join(root_path, "onionshare", "resources", "tor") dist_path = os.path.join(root_path, "onionshare", "resources", "tor")
# Make sure dirs exist # Make sure dirs exist
@ -203,25 +193,29 @@ def get_tor_linux64():
print("Downloading {}".format(linux64_url)) print("Downloading {}".format(linux64_url))
r = requests.get(linux64_url) r = requests.get(linux64_url)
open(tarball_path, "wb").write(r.content) open(tarball_path, "wb").write(r.content)
tarball_sha256 = hashlib.sha256(r.content).hexdigest()
else:
tarball_data = open(tarball_path, "rb").read()
tarball_sha256 = hashlib.sha256(tarball_data).hexdigest()
# Compare the hash # Make sure the signature file is downloaded
if tarball_sha256 != expected_linux64_sha256: if not os.path.exists(tarball_sig_path):
print("ERROR! The sha256 doesn't match:") print("Downloading {}".format(expected_linux64_sig))
print("expected: {}".format(expected_linux64_sha256)) r = requests.get(expected_linux64_sig)
print(" actual: {}".format(tarball_sha256)) open(tarball_sig_path, "wb").write(r.content)
# Verify signature
sig_stream = open(tarball_sig_path, "rb")
verified = gpg.verify_file(sig_stream, tarball_path)
if not verified.valid or verified.pubkey_fingerprint != tor_dev_fingerprint:
print("ERROR! The tarball verification with the signature failed!")
sys.exit(-1) sys.exit(-1)
print("Tor Browser verification successful!")
# Delete extracted tarball, if it's there # Delete extracted tarball, if it's there
shutil.rmtree(os.path.join(working_path, "tor-browser_en-US"), ignore_errors=True) shutil.rmtree(os.path.join(working_path, "tor-browser"), ignore_errors=True)
# Extract the tarball # Extract the tarball
subprocess.call(["tar", "-xvf", tarball_path], cwd=working_path) subprocess.call(["tar", "-xvf", tarball_path], cwd=working_path)
tarball_tor_path = os.path.join( tarball_tor_path = os.path.join(
working_path, "tor-browser_en-US", "Browser", "TorBrowser" working_path, "tor-browser", "Browser", "TorBrowser"
) )
# Copy into dist # Copy into dist
@ -321,17 +315,29 @@ def main(platform):
click.echo(f"platform must be one of: {valid_platforms}") click.echo(f"platform must be one of: {valid_platforms}")
return return
(
platform_url,
platform_filename,
expected_platform_sig,
) = get_latest_tor_version_urls(platform)
tmpdir = tempfile.TemporaryDirectory()
gpg = gnupg.GPG(gnupghome=tmpdir.name)
torkey = gpg.import_keys_file(os.path.join(root_path, "scripts", "kounek7zrdx745qydx6p59t9mqjpuhdf"))
print(f"Imported Tor GPG key: {torkey.fingerprints}")
if platform == "win32": if platform == "win32":
get_tor_windows(platform) get_tor_windows(gpg, torkey, platform_url, platform_filename, expected_platform_sig)
elif platform == "win64": elif platform == "win64":
get_tor_windows(platform) get_tor_windows(gpg, torkey, platform_url, platform_filename, expected_platform_sig)
elif platform == "macos": elif platform == "macos":
get_tor_macos() get_tor_macos(gpg, torkey, platform_url, platform_filename, expected_platform_sig)
elif platform == "linux64": elif platform == "linux64":
get_tor_linux64() get_tor_linux64(gpg, torkey, platform_url, platform_filename, expected_platform_sig)
else: else:
click.echo("invalid platform") click.echo("invalid platform")
tmpdir.cleanup()
if __name__ == "__main__": if __name__ == "__main__":
main() main()

Binary file not shown.

View File

@ -0,0 +1,43 @@
#!/usr/bin/env python3
import os, subprocess, sys
def main(argv):
if len(argv) != 2:
print("Usage: check-arch.py PATH_TO_APP", file = sys.stderr)
sys.exit(-1)
universal = []
silicon = []
intel = []
for d in os.walk(argv[1]):
ap = os.path.join(os.path.abspath('.'),d[0])
for f in os.listdir(ap):
fl = os.path.join(ap,f)
if os.path.isfile(fl):
a = subprocess.run(['file',fl], stdout = subprocess.PIPE)
b = a.stdout.decode('utf-8')
if 'binary' in b or 'executable' in b or 'library' in b:
arm64, x86 = False, False
if 'arm64' in b:
arm64 = True
if 'x86_64' in b:
x86 = True
if arm64 and x86:
universal += [fl]
elif arm64:
silicon += [fl]
elif x86:
intel += [fl]
with open('macos-check-arch.log', 'w') as fout:
fout.write('-*- Universal -*-\n')
for p in universal:
fout.write(p+'\n')
fout.write('\n-*- Silicon -*-\n')
for p in silicon:
fout.write(p+'\n')
fout.write('\n-*- Intel -*-\n')
for p in intel:
fout.write(p+'\n')
if __name__ == '__main__':
main(sys.argv)

View File

@ -26,85 +26,6 @@ import cx_Freeze
from cx_Freeze import setup, Executable from cx_Freeze import setup, Executable
from setuptools import find_packages from setuptools import find_packages
# There's an obscure cx_Freeze bug that I'm hitting that's preventing the macOS
# package from getting built. This is some monkeypatching to fix it.
if platform.system() == "Darwin" or platform.system() == "Linux":
import importlib_metadata
import pathlib
from pathlib import Path
from tempfile import TemporaryDirectory
class CustomPackagePath(pathlib.PurePosixPath):
def __init__(self, filename):
self.long_filename = str(filename)
self.short_filename = "/".join(filename.as_posix().split("/")[-2:])
super(CustomPackagePath, self).__init__()
def read_text(self, encoding="utf-8"):
with self.locate().open(encoding=encoding) as stream:
return stream.read()
def read_binary(self):
with self.locate().open("rb") as stream:
return stream.read()
def locate(self):
return Path(self.long_filename)
def as_posix(self):
return self.short_filename
class DistributionCache(importlib_metadata.PathDistribution):
_cachedir = TemporaryDirectory(prefix="cxfreeze-")
@staticmethod
def at(path):
return DistributionCache(Path(path))
at.__doc__ = importlib_metadata.PathDistribution.at.__doc__
@classmethod
def from_name(cls, name):
distribution = super().from_name(name)
temp_dir = Path(cls._cachedir.name)
dist_dir = None
files = distribution.files or []
prep = importlib_metadata.Prepared(distribution.name)
normalized = prep.normalized
legacy_normalized = prep.legacy_normalized
for file in files:
# patch: the onionshare and onionshare_cli files are using absolute paths, which break everything
if name in ["onionshare", "onionshare_cli"]:
if ".dist-info" not in file.as_posix():
continue
file = CustomPackagePath(file)
if (
not file.match(f"{name}-*.dist-info/*")
and not file.match(f"{distribution.name}-*.dist-info/*")
and not file.match(f"{normalized}-*.dist-info/*")
and not file.match(f"{legacy_normalized}-*.dist-info/*")
):
continue
src_path = file.locate()
if not src_path.exists():
continue
dst_path = temp_dir / file.as_posix()
if dist_dir is None:
dist_dir = dst_path.parent
dist_dir.mkdir(exist_ok=True)
shutil.copy2(src_path, dst_path)
if dist_dir is None:
raise importlib_metadata.PackageNotFoundError(name)
return cls.at(dist_dir)
from_name.__doc__ = importlib_metadata.PathDistribution.from_name.__doc__
cx_Freeze.module.DistributionCache = DistributionCache
# Discover the version # Discover the version
with open(os.path.join("..", "cli", "onionshare_cli", "resources", "version.txt")) as f: with open(os.path.join("..", "cli", "onionshare_cli", "resources", "version.txt")) as f:
version = f.read().strip() version = f.read().strip()
@ -123,20 +44,20 @@ if platform.system() == "Windows":
exec_icon = os.path.join("onionshare", "resources", "onionshare.ico") exec_icon = os.path.join("onionshare", "resources", "onionshare.ico")
elif platform.system() == "Darwin": elif platform.system() == "Darwin":
import PySide2 import PySide6
import shiboken2 import shiboken6
include_msvcr = False include_msvcr = False
gui_base = None gui_base = None
exec_icon = None exec_icon = None
include_files += [ include_files += [
( (
os.path.join(PySide2.__path__[0], "libpyside2.abi3.5.15.dylib"), os.path.join(PySide6.__path__[0], "libpyside6.abi3.6.4.dylib"),
"libpyside2.abi3.5.15.dylib", "libpyside6.abi3.6.4.dylib",
), ),
( (
os.path.join(shiboken2.__path__[0], "libshiboken2.abi3.5.15.dylib"), os.path.join(shiboken6.__path__[0], "libshiboken6.abi3.6.4.dylib"),
"libshiboken2.abi3.5.15.dylib", "libshiboken6.abi3.6.4.dylib",
), ),
] ]
@ -170,53 +91,53 @@ setup(
"jinja2.ext", "jinja2.ext",
"onionshare", "onionshare",
"onionshare_cli", "onionshare_cli",
"PySide2", "PySide6",
"PySide2.QtCore", "PySide6.QtCore",
"PySide2.QtGui", "PySide6.QtGui",
"PySide2.QtWidgets", "PySide6.QtWidgets",
], ],
"excludes": [ "excludes": [
"test", "test",
"tkinter", "tkinter",
"PySide2.Qt3DAnimation", "PySide6.Qt3DAnimation",
"PySide2.Qt3DCore", "PySide6.Qt3DCore",
"PySide2.Qt3DExtras", "PySide6.Qt3DExtras",
"PySide2.Qt3DInput", "PySide6.Qt3DInput",
"PySide2.Qt3DLogic", "PySide6.Qt3DLogic",
"PySide2.Qt3DRender", "PySide6.Qt3DRender",
"PySide2.QtCharts", "PySide6.QtCharts",
"PySide2.QtConcurrent", "PySide6.QtConcurrent",
"PySide2.QtDataVisualization", "PySide6.QtDataVisualization",
"PySide2.QtHelp", "PySide6.QtHelp",
"PySide2.QtLocation", "PySide6.QtLocation",
"PySide2.QtMultimedia", "PySide6.QtMultimedia",
"PySide2.QtMultimediaWidgets", "PySide6.QtMultimediaWidgets",
"PySide2.QtNetwork", "PySide6.QtNetwork",
"PySide2.QtOpenGL", "PySide6.QtOpenGL",
"PySide2.QtOpenGLFunctions", "PySide6.QtOpenGLFunctions",
"PySide2.QtPositioning", "PySide6.QtPositioning",
"PySide2.QtPrintSupport", "PySide6.QtPrintSupport",
"PySide2.QtQml", "PySide6.QtQml",
"PySide2.QtQuick", "PySide6.QtQuick",
"PySide2.QtQuickControls2", "PySide6.QtQuickControls2",
"PySide2.QtQuickWidgets", "PySide6.QtQuickWidgets",
"PySide2.QtRemoteObjects", "PySide6.QtRemoteObjects",
"PySide2.QtScript", "PySide6.QtScript",
"PySide2.QtScriptTools", "PySide6.QtScriptTools",
"PySide2.QtScxml", "PySide6.QtScxml",
"PySide2.QtSensors", "PySide6.QtSensors",
"PySide2.QtSerialPort", "PySide6.QtSerialPort",
"PySide2.QtSql", "PySide6.QtSql",
"PySide2.QtTest", "PySide6.QtTest",
"PySide2.QtTextToSpeech", "PySide6.QtTextToSpeech",
"PySide2.QtUiTools", "PySide6.QtUiTools",
"PySide2.QtWebChannel", "PySide6.QtWebChannel",
"PySide2.QtWebEngine", "PySide6.QtWebEngine",
"PySide2.QtWebEngineCore", "PySide6.QtWebEngineCore",
"PySide2.QtWebEngineWidgets", "PySide6.QtWebEngineWidgets",
"PySide2.QtWebSockets", "PySide6.QtWebSockets",
"PySide2.QtXml", "PySide6.QtXml",
"PySide2.QtXmlPatterns", "PySide6.QtXmlPatterns",
], ],
"include_files": include_files, "include_files": include_files,
"include_msvcr": include_msvcr, "include_msvcr": include_msvcr,

View File

@ -2,7 +2,7 @@ import sys
import os import os
from datetime import datetime, timedelta from datetime import datetime, timedelta
from PySide2 import QtTest from PySide6 import QtTest
# Force tests to look for resources in the source code tree # Force tests to look for resources in the source code tree
@ -19,7 +19,7 @@ def qWait(t, qtapp):
qtapp.processEvents() qtapp.processEvents()
# Monkeypatch qWait, because PySide2 doesn't have it # Monkeypatch qWait, although PySide6 has it
# https://stackoverflow.com/questions/17960159/qwait-analogue-in-pyside # https://stackoverflow.com/questions/17960159/qwait-analogue-in-pyside
QtTest.QTest.qWait = qWait QtTest.QTest.qWait = qWait

View File

@ -7,7 +7,7 @@ import secrets
import platform import platform
import sys import sys
from PySide2 import QtCore, QtTest, QtWidgets from PySide6 import QtCore, QtTest, QtWidgets
from onionshare_cli.common import Common from onionshare_cli.common import Common

View File

@ -1,6 +1,6 @@
import requests import requests
from PySide2 import QtTest from PySide6 import QtTest
from .gui_base_test import GuiBaseTest from .gui_base_test import GuiBaseTest

View File

@ -6,7 +6,7 @@ import shutil
import sys import sys
from datetime import datetime, timedelta from datetime import datetime, timedelta
from PySide2 import QtCore, QtTest from PySide6 import QtCore, QtTest
from .gui_base_test import GuiBaseTest from .gui_base_test import GuiBaseTest

View File

@ -3,7 +3,7 @@ import requests
import tempfile import tempfile
import zipfile import zipfile
from PySide2 import QtCore, QtTest from PySide6 import QtCore, QtTest
from .gui_base_test import GuiBaseTest from .gui_base_test import GuiBaseTest

View File

@ -1,6 +1,6 @@
import os import os
from PySide2 import QtCore, QtTest, QtWidgets from PySide6 import QtCore, QtTest, QtWidgets
from .gui_base_test import GuiBaseTest from .gui_base_test import GuiBaseTest

View File

@ -1,6 +1,6 @@
import requests import requests
from PySide2 import QtTest from PySide6 import QtTest
from .gui_base_test import GuiBaseTest from .gui_base_test import GuiBaseTest

View File

@ -2,11 +2,11 @@
app-id: org.onionshare.OnionShare app-id: org.onionshare.OnionShare
command: onionshare command: onionshare
runtime: org.kde.Platform runtime: org.kde.Platform
runtime-version: "5.15-21.08" runtime-version: "6.4"
sdk: org.kde.Sdk sdk: org.kde.Sdk
sdk-extensions: sdk-extensions:
- org.freedesktop.Sdk.Extension.golang - org.freedesktop.Sdk.Extension.golang
- org.freedesktop.Sdk.Extension.llvm12 - org.freedesktop.Sdk.Extension.llvm15
separate-locales: false separate-locales: false
finish-args: finish-args:
- "--device=dri" - "--device=dri"
@ -22,33 +22,37 @@ cleanup:
- "/go" - "/go"
- "/bin/scripts" - "/bin/scripts"
modules: modules:
- name: pyside2 - name: pyside6
buildsystem: cmake-ninja buildsystem: simple
builddir: true build-commands: []
build-options: modules:
prepend-path: /usr/lib/sdk/llvm12/bin - name: pyside6-essentials
prepend-ld-library-path: /usr/lib/sdk/llvm12/lib only-arches:
config-opts: - x86_64
- -DCMAKE_BUILD_TYPE=Release buildsystem: simple
- -DBUILD_TESTS=OFF build-commands:
cleanup: - pip3 install --verbose --exists-action=i --no-index --find-links="file://${PWD}"
- /bin --prefix=${FLATPAK_DEST} "pyside6-essentials" --no-build-isolation
sources: sources:
- type: archive - type: file
sha256: f61210ae24e6882d5d0ca0059229e5dc4f35e2bca92dd6caf96c0f41943a8294 url: https://files.pythonhosted.org/packages/e5/96/f43cdcb397f8a8cff6991ef8109385cc5ad9b0ad78c6dc2988b3b776fe49/PySide6_Essentials-6.4.2-cp37-abi3-manylinux_2_28_x86_64.whl
url: https://download.qt.io/official_releases/QtForPython/pyside2/PySide2-5.15.7-src/pyside-setup-opensource-src-5.15.7.tar.xz sha256: 8c3d37cca6e27f6da12b50b20e741d593ccc857bdcdb82d97f8f7c8bfe53639a
- type: shell modules:
commands: - name: shiboken6
- mkdir -p /app/include/qt5tmp && cp -R /usr/include/Qt* /app/include/qt5tmp # https://bugreports.qt.io/browse/PYSIDE-787 buildsystem: simple
- sed -i 's|\(--include-paths=\)|\1/app/include/qt5tmp:|' sources/pyside2/cmake/Macros/PySideModules.cmake build-commands:
- sed -i s/'<private\/qaccessiblequickview_p.h>'/'\"private\/qaccessiblequickview_p.h\"'/ /app/include/qt5tmp/QtQuickWidgets/qaccessiblequickwidget.h - pip3 install --verbose --exists-action=i --no-index --find-links="file://${PWD}"
- mkdir -p /app/include/qt5tmp/QtQuickWidgets/private && cp /app/include/qt5tmp/QtQuick/5.15.7/QtQuick/private/qaccessiblequickview_p.h /app/include/qt5tmp/QtQuickWidgets/private/qaccessiblequickview_p.h --prefix=${FLATPAK_DEST} "shiboken6" --no-build-isolation
sources:
- type: file
url: https://files.pythonhosted.org/packages/24/f6/f1fe9220a616789a1c6b1b73670d8b1dec882ac730a8b534f963b3f26182/shiboken6-6.4.2-cp37-abi3-manylinux_2_28_x86_64.whl
sha256: 0616c1a12d1e51e680595b3940b986275c1df952a751416a0730a59e5b90105f
- name: tor - name: tor
buildsystem: autotools buildsystem: autotools
sources: sources:
- type: archive - type: archive
sha256: 3b5d969712c467851bd028f314343ef15a97ea457191e93ffa97310b05b9e395 sha256: d39d38598208f4d6201d7edc6ad573b3a898a932a5c68d3074016a9525519b22
url: https://dist.torproject.org/tor-0.4.7.12.tar.gz url: https://dist.torproject.org/tor-0.4.7.9.tar.gz
modules: modules:
- name: libevent - name: libevent
buildsystem: autotools buildsystem: autotools
@ -279,7 +283,7 @@ modules:
dest: src/github.com/xtaci/kcp-go dest: src/github.com/xtaci/kcp-go
- type: git - type: git
url: https://github.com/xtaci/smux url: https://github.com/xtaci/smux
commit: '09e2c01560df5aaaed50e48e77547858e2623498' commit: "09e2c01560df5aaaed50e48e77547858e2623498"
dest: src/github.com/xtaci/smux dest: src/github.com/xtaci/smux
- type: git - type: git
url: https://github.com/klauspost/cpuid url: https://github.com/klauspost/cpuid
@ -308,6 +312,10 @@ modules:
# - type: git # - type: git
# url: https://github.com/onionshare/onionshare.git # url: https://github.com/onionshare/onionshare.git
# tag: v2.6 # tag: v2.6
modules:
- name: python3-modules
buildsystem: simple
build-commands: []
modules: modules:
- name: python3-qrcode - name: python3-qrcode
buildsystem: simple buildsystem: simple
@ -316,8 +324,26 @@ modules:
--prefix=${FLATPAK_DEST} "qrcode" --no-build-isolation --prefix=${FLATPAK_DEST} "qrcode" --no-build-isolation
sources: sources:
- type: file - type: file
url: https://files.pythonhosted.org/packages/94/9f/31f33cdf3cf8f98e64c42582fb82f39ca718264df61957f28b0bbb09b134/qrcode-7.3.1.tar.gz url: https://files.pythonhosted.org/packages/3e/b9/3766cc361d93edb2ce81e2e1f87dd98f314d7d513877a342d31b30741680/pypng-0.20220715.0-py3-none-any.whl
sha256: 375a6ff240ca9bd41adc070428b5dfc1dcfbb0f2507f1ac848f6cded38956578 sha256: 4a43e969b8f5aaafb2a415536c1a8ec7e341cd6a3f957fd5b5f32a4cfeed902c
- type: file
url: https://files.pythonhosted.org/packages/24/79/aaf0c1c7214f2632badb2771d770b1500d3d7cbdf2590ae62e721ec50584/qrcode-7.4.2-py3-none-any.whl
sha256: 581dca7a029bcb2deef5d01068e39093e80ef00b4a61098a2182eac59d01643a
- type: file
url: https://files.pythonhosted.org/packages/0b/8e/f1a0a5a76cfef77e1eb6004cb49e5f8d72634da638420b9ea492ce8305e8/typing_extensions-4.4.0-py3-none-any.whl
sha256: 16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e
- name: python3-werkzeug
buildsystem: simple
build-commands:
- pip3 install --verbose --exists-action=i --no-index --find-links="file://${PWD}"
--prefix=${FLATPAK_DEST} "werkzeug" --no-build-isolation
sources:
- type: file
url: https://files.pythonhosted.org/packages/95/7e/68018b70268fb4a2a605e2be44ab7b4dd7ce7808adae6c5ef32e34f4b55a/MarkupSafe-2.1.2.tar.gz
sha256: abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d
- type: file
url: https://files.pythonhosted.org/packages/c8/27/be6ddbcf60115305205de79c29004a0c6bc53cec814f733467b1bb89386d/Werkzeug-2.2.2-py3-none-any.whl
sha256: f979ab81f58d7318e064e99c4506445d60135ac5cd2e177a2de0089bfd4c9bd5
- name: onionshare-cli - name: onionshare-cli
buildsystem: simple buildsystem: simple
build-commands: build-commands:
@ -333,49 +359,42 @@ modules:
buildsystem: simple buildsystem: simple
build-commands: build-commands:
- pip3 install --no-index --find-links="file://${PWD}" --prefix=${FLATPAK_DEST} - pip3 install --no-index --find-links="file://${PWD}" --prefix=${FLATPAK_DEST}
wheel Cython attrs bidict certifi cffi charset-normalizer click colorama dnspython eventlet
- pip3 install --no-index --find-links="file://${PWD}" --prefix=${FLATPAK_DEST} exceptiongroup flask flask-socketio gevent gevent-websocket greenlet idna iniconfig
atomicwrites attrs bidict certifi cffi charset-normalizer click colorama itsdangerous jinja2 markupsafe packaging pluggy psutil pycparser pynacl pysocks
dnspython eventlet Flask Flask-SocketIO gevent gevent-websocket greenlet idna pytest python-engineio python-socketio requests setuptools six stem tomli unidecode
importlib-metadata iniconfig itsdangerous Jinja2 MarkupSafe packaging pluggy psutil urllib3 werkzeug zope-event zope-interface setuptools wheel Cython
py pycparser PyNaCl pyparsing PySocks pytest python-engineio python-socketio requests
setuptools six stem tomli typing-extensions Unidecode urllib3 Werkzeug zipp
- pip3 install --no-index --find-links="file://${PWD}" --prefix=${FLATPAK_DEST}
zope.event zope.interface
sources: sources:
- type: file - type: file
url: https://files.pythonhosted.org/packages/87/c6/53da25344e3e3a9c01095a89f16dbcda021c609ddb42dd6d7c0528236fb2/atomicwrites-1.4.1.tar.gz url: https://files.pythonhosted.org/packages/fb/6e/6f83bf616d2becdf333a1640f1d463fef3150e2e926b7010cb0f81c95e88/attrs-22.2.0-py3-none-any.whl
sha256: 81b2c9071a49367a7f770170e5eec8cb66567cfbbc8c73d20ce5ca4a8d71cf11 sha256: 29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836
- type: file - type: file
url: https://files.pythonhosted.org/packages/f2/bc/d817287d1aa01878af07c19505fafd1165cd6a119e9d0821ca1d1c20312d/attrs-22.1.0-py2.py3-none-any.whl url: https://files.pythonhosted.org/packages/b5/82/ce0b6380f35f49d3fe687979a324c342cfa3588380232f3801db9dd62f9e/bidict-0.22.1-py3-none-any.whl
sha256: 86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c sha256: 6ef212238eb884b664f28da76f33f1d28b260f665fc737b413b287d5487d1e7b
- type: file - type: file
url: https://files.pythonhosted.org/packages/f1/04/ac51cac8d2b792a8de216c775248a371bf1da25f11d919f3528975288e21/bidict-0.21.4-py3-none-any.whl url: https://files.pythonhosted.org/packages/71/4c/3db2b8021bd6f2f0ceb0e088d6b2d49147671f25832fb17970e9b583d742/certifi-2022.12.7-py3-none-any.whl
sha256: 3ac67daa353ecf853a1df9d3e924f005e729227a60a8dbada31a4c31aba7f654 sha256: 4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18
- type: file
url: https://files.pythonhosted.org/packages/1d/38/fa96a426e0c0e68aabc68e896584b83ad1eec779265a028e156ce509630e/certifi-2022.9.24-py3-none-any.whl
sha256: 90c1a32f1d68f940488354e36370f6cca89f0f106db09518524c88d6ed83f382
- type: file - type: file
url: https://files.pythonhosted.org/packages/2b/a8/050ab4f0c3d4c1b8aaa805f70e26e84d0e27004907c5b8ecc1d31815f92a/cffi-1.15.1.tar.gz url: https://files.pythonhosted.org/packages/2b/a8/050ab4f0c3d4c1b8aaa805f70e26e84d0e27004907c5b8ecc1d31815f92a/cffi-1.15.1.tar.gz
sha256: d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9 sha256: d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9
- type: file - type: file
url: https://files.pythonhosted.org/packages/06/b3/24afc8868eba069a7f03650ac750a778862dc34941a4bebeb58706715726/charset_normalizer-2.0.12-py3-none-any.whl url: https://files.pythonhosted.org/packages/68/2b/02e9d6a98ddb73fa238d559a9edcc30b247b8dc4ee848b6184c936e99dc0/charset_normalizer-3.0.1-py3-none-any.whl
sha256: 6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df sha256: 7e189e2e1d3ed2f4aebabd2d5b0f931e883676e51c7624826e0a4e5fe8a0bf24
- type: file - type: file
url: https://files.pythonhosted.org/packages/4a/a8/0b2ced25639fb20cc1c9784de90a8c25f9504a7f18cd8b5397bd61696d7d/click-8.0.4-py3-none-any.whl url: https://files.pythonhosted.org/packages/c2/f1/df59e28c642d583f7dacffb1e0965d0e00b218e0186d7858ac5233dce840/click-8.1.3-py3-none-any.whl
sha256: 6a7a62563bbfabfda3a38f3023a1db4a35978c0abd76f6c9605ecd6554d6d9b1 sha256: bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48
- type: file - type: file
url: https://files.pythonhosted.org/packages/77/8b/7550e87b2d308a1b711725dfaddc19c695f8c5fa413c640b2be01662f4e6/colorama-0.4.5-py2.py3-none-any.whl url: https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl
sha256: 854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da sha256: 4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6
# - type: file
# url: https://files.pythonhosted.org/packages/fe/ca/75fac5856ab5cfa51bbbcefa250182e50441074fdc3f803f6e76451fab43/dataclasses-0.8-py3-none-any.whl
# sha256: 0201d89fa866f68c8ebd9d08ee6ff50c0b255f8ec63a71c16fda7af82bb887bf
- type: file - type: file
url: https://files.pythonhosted.org/packages/9b/ed/28fb14146c7033ba0e89decd92a4fa16b0b69b84471e2deab3cc4337cc35/dnspython-2.2.1-py3-none-any.whl url: https://files.pythonhosted.org/packages/12/86/d305e87555430ff4630d729420d97dece3b16efcbf2b7d7e974d11b0d86c/dnspython-2.3.0-py3-none-any.whl
sha256: a851e51367fb93e9e1361732c1d60dab63eff98712e503ea7d92e6eccb109b4f sha256: 89141536394f909066cabd112e3e1a37e4e654db00a25308b0f130bc3152eb46
- type: file - type: file
url: https://files.pythonhosted.org/packages/20/c0/b8796b6b965f9804b72baccc64b621241736cad7d5f6028ca7bcd0543b8f/eventlet-0.33.1-py2.py3-none-any.whl url: https://files.pythonhosted.org/packages/90/97/928b89de2e23cc67136eccccf1c122adf74ffdb65bbf7d2964b937cedd4f/eventlet-0.33.3-py2.py3-none-any.whl
sha256: a085922698e5029f820cf311a648ac324d73cec0e4792877609d978a4b5bbf31 sha256: e43b9ae05ba4bb477a10307699c9aff7ff86121b2640f9184d29059f5a687df8
- type: file
url: https://files.pythonhosted.org/packages/e8/14/9c6a7e5f12294ccd6975a45e02899ed25468cd7c2c86f3d9725f387f9f5f/exceptiongroup-1.1.0-py3-none-any.whl
sha256: 327cbda3da756e2de031a3107b81ab7b3770a602c4d16ca618298c526f4bec1e
- type: file - type: file
url: https://files.pythonhosted.org/packages/cd/77/59df23681f4fd19b7cbbb5e92484d46ad587554f5d490f33ef907e456132/Flask-2.0.3-py3-none-any.whl url: https://files.pythonhosted.org/packages/cd/77/59df23681f4fd19b7cbbb5e92484d46ad587554f5d490f33ef907e456132/Flask-2.0.3-py3-none-any.whl
sha256: 59da8a3170004800a2837844bfa84d49b022550616070f7cb1a659682b2e7c9f sha256: 59da8a3170004800a2837844bfa84d49b022550616070f7cb1a659682b2e7c9f
@ -383,71 +402,62 @@ modules:
url: https://files.pythonhosted.org/packages/a0/39/6899b61349cbcb19e84c948fbc8fc216c20d113e0e1ea996cf8fe5d50ee5/Flask_SocketIO-5.3.1-py3-none-any.whl url: https://files.pythonhosted.org/packages/a0/39/6899b61349cbcb19e84c948fbc8fc216c20d113e0e1ea996cf8fe5d50ee5/Flask_SocketIO-5.3.1-py3-none-any.whl
sha256: ff0c721f20bff1e2cfba77948727a8db48f187e89a72fe50c34478ce6efb3353 sha256: ff0c721f20bff1e2cfba77948727a8db48f187e89a72fe50c34478ce6efb3353
- type: file - type: file
url: https://files.pythonhosted.org/packages/c8/18/631398e45c109987f2d8e57f3adda161cc5ff2bd8738ca830c3a2dd41a85/gevent-21.12.0.tar.gz url: https://files.pythonhosted.org/packages/9f/4a/e9e57cb9495f0c7943b1d5965c4bdd0d78bc4a433a7c96ee034b16c01520/gevent-22.10.2.tar.gz
sha256: f48b64578c367b91fa793bf8eaaaf4995cb93c8bc45860e473bf868070ad094e sha256: 1ca01da176ee37b3527a2702f7d40dbc9ffb8cfc7be5a03bfa4f9eec45e55c46
- type: file - type: file
url: https://files.pythonhosted.org/packages/7b/84/2dc373eb6493e00c884cc11e6c059ec97abae2678d42f06bf780570b0193/gevent_websocket-0.10.1-py3-none-any.whl url: https://files.pythonhosted.org/packages/7b/84/2dc373eb6493e00c884cc11e6c059ec97abae2678d42f06bf780570b0193/gevent_websocket-0.10.1-py3-none-any.whl
sha256: 17b67d91282f8f4c973eba0551183fc84f56f1c90c8f6b6b30256f31f66f5242 sha256: 17b67d91282f8f4c973eba0551183fc84f56f1c90c8f6b6b30256f31f66f5242
- type: file - type: file
url: https://files.pythonhosted.org/packages/a0/d5/70772b3693f086a362f122516225a43fe4f1182e17158c81ba1ab271ab9b/greenlet-1.1.3.tar.gz url: https://files.pythonhosted.org/packages/1e/1e/632e55a04d732c8184201238d911207682b119c35cecbb9a573a6c566731/greenlet-2.0.2.tar.gz
sha256: bcb6c6dd1d6be6d38d6db283747d07fda089ff8c559a835236560a4410340455 sha256: e7c8dc13af7db097bed64a051d2dd49e9f0af495c26995c00a9ee842690d34c0
- type: file - type: file
url: https://files.pythonhosted.org/packages/fc/34/3030de6f1370931b9dbb4dad48f6ab1015ab1d32447850b9fc94e60097be/idna-3.4-py3-none-any.whl url: https://files.pythonhosted.org/packages/fc/34/3030de6f1370931b9dbb4dad48f6ab1015ab1d32447850b9fc94e60097be/idna-3.4-py3-none-any.whl
sha256: 90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2 sha256: 90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2
- type: file - type: file
url: https://files.pythonhosted.org/packages/a0/a1/b153a0a4caf7a7e3f15c2cd56c7702e2cf3d89b1b359d1f1c5e59d68f4ce/importlib_metadata-4.8.3-py3-none-any.whl url: https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl
sha256: 65a9576a5b2d58ca44d133c42a241905cc45e34d2c06fd5ba2bafa221e5d7b5e sha256: b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374
- type: file - type: file
url: https://files.pythonhosted.org/packages/9b/dd/b3c12c6d707058fa947864b67f0c4e0c39ef8610988d7baea9578f3c48f3/iniconfig-1.1.1-py2.py3-none-any.whl url: https://files.pythonhosted.org/packages/68/5f/447e04e828f47465eeab35b5d408b7ebaaaee207f48b7136c5a7267a30ae/itsdangerous-2.1.2-py3-none-any.whl
sha256: 011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3 sha256: 2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44
- type: file - type: file
url: https://files.pythonhosted.org/packages/9c/96/26f935afba9cd6140216da5add223a0c465b99d0f112b68a4ca426441019/itsdangerous-2.0.1-py3-none-any.whl url: https://files.pythonhosted.org/packages/bc/c3/f068337a370801f372f2f8f6bad74a5c140f6fda3d9de154052708dd3c65/Jinja2-3.1.2-py3-none-any.whl
sha256: 5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c sha256: 6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61
- type: file - type: file
url: https://files.pythonhosted.org/packages/20/9a/e5d9ec41927401e41aea8af6d16e78b5e612bca4699d417f646a9610a076/Jinja2-3.0.3-py3-none-any.whl url: https://files.pythonhosted.org/packages/95/7e/68018b70268fb4a2a605e2be44ab7b4dd7ce7808adae6c5ef32e34f4b55a/MarkupSafe-2.1.2.tar.gz
sha256: 077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8 sha256: abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d
- type: file - type: file
url: https://files.pythonhosted.org/packages/bf/10/ff66fea6d1788c458663a84d88787bae15d45daa16f6b3ef33322a51fc7e/MarkupSafe-2.0.1.tar.gz url: https://files.pythonhosted.org/packages/ed/35/a31aed2993e398f6b09a790a181a7927eb14610ee8bbf02dc14d31677f1c/packaging-23.0-py3-none-any.whl
sha256: 594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a sha256: 714ac14496c3e68c99c29b00845f7a2b85f3bb6f1078fd9f72fd20f0570002b2
- type: file
url: https://files.pythonhosted.org/packages/05/8e/8de486cbd03baba4deef4142bd643a3e7bbe954a784dc1bb17142572d127/packaging-21.3-py3-none-any.whl
sha256: ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522
- type: file - type: file
url: https://files.pythonhosted.org/packages/9e/01/f38e2ff29715251cf25532b9082a1589ab7e4f571ced434f98d0139336dc/pluggy-1.0.0-py2.py3-none-any.whl url: https://files.pythonhosted.org/packages/9e/01/f38e2ff29715251cf25532b9082a1589ab7e4f571ced434f98d0139336dc/pluggy-1.0.0-py2.py3-none-any.whl
sha256: 74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3 sha256: 74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3
- type: file - type: file
url: https://files.pythonhosted.org/packages/8f/57/828ac1f70badc691a716e77bfae258ef5db76bb7830109bf4bcf882de020/psutil-5.9.2.tar.gz url: https://files.pythonhosted.org/packages/3d/7d/d05864a69e452f003c0d77e728e155a89a2a26b09e64860ddd70ad64fb26/psutil-5.9.4.tar.gz
sha256: feb861a10b6c3bb00701063b37e4afc754f8217f0f09c42280586bd6ac712b5c sha256: 3d7f9739eb435d4b1338944abe23f49584bde5395f27487d2ee25ad9a8774a62
- type: file
url: https://files.pythonhosted.org/packages/f6/f0/10642828a8dfb741e5f3fbaac830550a518a775c7fff6f04a007259b0548/py-1.11.0-py2.py3-none-any.whl
sha256: 607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378
- type: file - type: file
url: https://files.pythonhosted.org/packages/62/d5/5f610ebe421e85889f2e55e33b7f9a6795bd982198517d912eb1c76e1a53/pycparser-2.21-py2.py3-none-any.whl url: https://files.pythonhosted.org/packages/62/d5/5f610ebe421e85889f2e55e33b7f9a6795bd982198517d912eb1c76e1a53/pycparser-2.21-py2.py3-none-any.whl
sha256: 8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9 sha256: 8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9
- type: file - type: file
url: https://files.pythonhosted.org/packages/a7/22/27582568be639dfe22ddb3902225f91f2f17ceff88ce80e4db396c8986da/PyNaCl-1.5.0.tar.gz url: https://files.pythonhosted.org/packages/a7/22/27582568be639dfe22ddb3902225f91f2f17ceff88ce80e4db396c8986da/PyNaCl-1.5.0.tar.gz
sha256: 8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba sha256: 8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba
- type: file
url: https://files.pythonhosted.org/packages/80/c1/23fd82ad3121656b585351aba6c19761926bb0db2ebed9e4ff09a43a3fcc/pyparsing-3.0.7-py3-none-any.whl
sha256: a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484
- type: file - type: file
url: https://files.pythonhosted.org/packages/8d/59/b4572118e098ac8e46e399a1dd0f2d85403ce8bbaad9ec79373ed6badaf9/PySocks-1.7.1-py3-none-any.whl url: https://files.pythonhosted.org/packages/8d/59/b4572118e098ac8e46e399a1dd0f2d85403ce8bbaad9ec79373ed6badaf9/PySocks-1.7.1-py3-none-any.whl
sha256: 2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5 sha256: 2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5
- type: file - type: file
url: https://files.pythonhosted.org/packages/38/93/c7c0bd1e932b287fb948eb9ce5a3d6307c9fc619db1e199f8c8bc5dad95f/pytest-7.0.1-py3-none-any.whl url: https://files.pythonhosted.org/packages/cc/02/8f59bf194c9a1ceac6330850715e9ec11e21e2408a30a596c65d54cf4d2a/pytest-7.2.1-py3-none-any.whl
sha256: 9ce3ff477af913ecf6321fe337b93a2c0dcf2a0a1439c43f5452112c1e4280db sha256: c7c6ca206e93355074ae32f7403e8ea12163b1163c976fee7d4d84027c162be5
- type: file - type: file
url: https://files.pythonhosted.org/packages/45/ba/aa28ea42cbe8a133004f1cfe799bbd11d56f24c6fb588feea4d1dffeb148/python_engineio-4.3.4-py3-none-any.whl url: https://files.pythonhosted.org/packages/45/ba/aa28ea42cbe8a133004f1cfe799bbd11d56f24c6fb588feea4d1dffeb148/python_engineio-4.3.4-py3-none-any.whl
sha256: 7454314a529bba20e745928601ffeaf101c1b5aca9a6c4e48ad397803d10ea0c sha256: 7454314a529bba20e745928601ffeaf101c1b5aca9a6c4e48ad397803d10ea0c
- type: file - type: file
url: https://files.pythonhosted.org/packages/d3/b0/862b095d2c6e7892c7be2056efe02d4faea62ee35b3ed10b905fdfa3d74a/python_socketio-5.7.1-py3-none-any.whl url: https://files.pythonhosted.org/packages/5c/27/3a215e5fc16e371fa8e9bca75d37e120d05c8dd5030905b6657ae8c96d13/python_socketio-5.7.2-py3-none-any.whl
sha256: 86ee93591c1e781d339d9a61940e62fd6cbc838390653b52a7bcc4f7ce89fe47 sha256: d9a9f047e6fdd306c852fbac36516f4b495c2096f8ad9ceb8803b8e5ff5622e3
- type: file - type: file
url: https://files.pythonhosted.org/packages/2d/61/08076519c80041bc0ffa1a8af0cbd3bf3e2b62af10435d269a9d0f40564d/requests-2.27.1-py2.py3-none-any.whl url: https://files.pythonhosted.org/packages/d2/f4/274d1dbe96b41cf4e0efb70cbced278ffd61b5c7bb70338b62af94ccb25b/requests-2.28.2-py3-none-any.whl
sha256: f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d sha256: 64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa
- type: file - type: file
url: https://files.pythonhosted.org/packages/b0/3a/88b210db68e56854d0bcf4b38e165e03be377e13907746f825790f3df5bf/setuptools-59.6.0-py3-none-any.whl url: https://files.pythonhosted.org/packages/c8/24/157fed9a57108b3e1b6ccd86e95823327f231ef12464b0eca13650eb33ac/setuptools-67.1.0-py3-none-any.whl
sha256: 4ce92f1e1f8f01233ee9952c04f6b81d1e02939d6e1b488428154974a4d0783e sha256: a7687c12b444eaac951ea87a9627c4f904ac757e7abdc5aac32833234af90378
- type: file - type: file
url: https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl url: https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl
sha256: 8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 sha256: 8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254
@ -455,32 +465,29 @@ modules:
url: https://files.pythonhosted.org/packages/b2/66/c5515de764bffae1347e671819711268da5c02bfab8406223526822fe5f6/stem-1.8.1.tar.gz url: https://files.pythonhosted.org/packages/b2/66/c5515de764bffae1347e671819711268da5c02bfab8406223526822fe5f6/stem-1.8.1.tar.gz
sha256: 81d43a7c668ba9d7bc1103b2e7a911e9d148294b373d27a59ae8da79ef7a3e2f sha256: 81d43a7c668ba9d7bc1103b2e7a911e9d148294b373d27a59ae8da79ef7a3e2f
- type: file - type: file
url: https://files.pythonhosted.org/packages/05/e4/74f9440db36734d7ba83c574c1e7024009ce849208a41f90e94a134dc6d1/tomli-1.2.3-py3-none-any.whl url: https://files.pythonhosted.org/packages/97/75/10a9ebee3fd790d20926a90a2547f0bf78f371b2f13aa822c759680ca7b9/tomli-2.0.1-py3-none-any.whl
sha256: e3069e4be3ead9668e21cb9b074cd948f7b3113fd9c8bba083f48247aab8b11c sha256: 939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc
- type: file
url: https://files.pythonhosted.org/packages/45/6b/44f7f8f1e110027cf88956b59f2fad776cca7e1704396d043f89effd3a0e/typing_extensions-4.1.1-py3-none-any.whl
sha256: 21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2
- type: file - type: file
url: https://files.pythonhosted.org/packages/be/ea/90e14e807da5a39e5b16789acacd48d63ca3e4f23dfa964a840eeadebb13/Unidecode-1.3.6-py3-none-any.whl url: https://files.pythonhosted.org/packages/be/ea/90e14e807da5a39e5b16789acacd48d63ca3e4f23dfa964a840eeadebb13/Unidecode-1.3.6-py3-none-any.whl
sha256: 547d7c479e4f377b430dd91ac1275d593308dce0fc464fb2ab7d41f82ec653be sha256: 547d7c479e4f377b430dd91ac1275d593308dce0fc464fb2ab7d41f82ec653be
- type: file - type: file
url: https://files.pythonhosted.org/packages/6f/de/5be2e3eed8426f871b170663333a0f627fc2924cc386cd41be065e7ea870/urllib3-1.26.12-py2.py3-none-any.whl url: https://files.pythonhosted.org/packages/fe/ca/466766e20b767ddb9b951202542310cba37ea5f2d792dae7589f1741af58/urllib3-1.26.14-py2.py3-none-any.whl
sha256: b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997 sha256: 75edcdc2f7d85b137124a6c3c9fc3933cdeaa12ecb9a6a959f22797a0feca7e1
- type: file - type: file
url: https://files.pythonhosted.org/packages/f4/f3/22afbdb20cc4654b10c98043414a14057cd27fdba9d4ae61cea596000ba2/Werkzeug-2.0.3-py3-none-any.whl url: https://files.pythonhosted.org/packages/f4/f3/22afbdb20cc4654b10c98043414a14057cd27fdba9d4ae61cea596000ba2/Werkzeug-2.0.3-py3-none-any.whl
sha256: 1421ebfc7648a39a5c58c601b154165d05cf47a3cd0ccb70857cbdacf6c8f2b8 sha256: 1421ebfc7648a39a5c58c601b154165d05cf47a3cd0ccb70857cbdacf6c8f2b8
- type: file - type: file
url: https://files.pythonhosted.org/packages/bd/df/d4a4974a3e3957fd1c1fa3082366d7fff6e428ddb55f074bf64876f8e8ad/zipp-3.6.0-py3-none-any.whl url: https://files.pythonhosted.org/packages/8b/a8/3ab9648dc08d2ab7543145ec174a2d982d08fb996d50d9a4d3e057da7132/zope.event-4.6-py2.py3-none-any.whl
sha256: 9fe5ea21568a0a70e50f273397638d39b03353731e6cbbb3fd8502a33fec40bc sha256: 73d9e3ef750cca14816a9c322c7250b0d7c9dbc337df5d1b807ff8d3d0b9e97c
- type: file - type: file
url: https://files.pythonhosted.org/packages/9e/85/b45408c64f3b888976f1d5b37eed8d746b8d5729a66a49ec846fda27d371/zope.event-4.5.0-py2.py3-none-any.whl url: https://files.pythonhosted.org/packages/38/6f/fbfb7dde38be7e5644bb342c4c7cdc444cd5e2ffbd70d091263b3858a8cb/zope.interface-5.5.2.tar.gz
sha256: 2666401939cdaa5f4e0c08cf7f20c9b21423b95e88f4675b1443973bdb080c42 sha256: bfee1f3ff62143819499e348f5b8a7f3aa0259f9aca5e0ddae7391d059dce671
- type: file - type: file
url: https://files.pythonhosted.org/packages/ae/58/e0877f58daa69126a5fb325d6df92b20b77431cd281e189c5ec42b722f58/zope.interface-5.4.0.tar.gz url: https://files.pythonhosted.org/packages/5f/36/7374297692bb9dbd7569a0f84887c7e5e314c41d5d9518cb76fbb130620d/setuptools-67.2.0.tar.gz
sha256: 5dba5f530fec3f0988d83b78cc591b58c0b6eb8431a85edd1569a0539a8a5a0e sha256: b440ee5f7e607bb8c9de15259dba2583dd41a38879a7abc1d43a71c59524da48
- type: file - type: file
url: https://files.pythonhosted.org/packages/27/d6/003e593296a85fd6ed616ed962795b2f87709c3eee2bca4f6d0fe55c6d00/wheel-0.37.1-py2.py3-none-any.whl url: https://files.pythonhosted.org/packages/a2/b8/6a06ff0f13a00fc3c3e7d222a995526cbca26c1ad107691b6b1badbbabf1/wheel-0.38.4.tar.gz
sha256: 4bdcd7d840138086126cd09254dc6195fb4fc6f01c050a1d7236f2630db1d22a sha256: 965f5259b566725405b05e7cf774052044b1ed30119b5d586b2703aafe8719ac
- type: file - type: file
url: https://files.pythonhosted.org/packages/2e/a7/f20fa91d9de799f8e19bacf225bc993b8a53b5fc6f41ffa20d64f0850579/Cython-3.0.0a11.tar.gz url: https://files.pythonhosted.org/packages/2e/a7/f20fa91d9de799f8e19bacf225bc993b8a53b5fc6f41ffa20d64f0850579/Cython-3.0.0a11.tar.gz
sha256: e4672491fb31546b9abb63677f638e738085dc9321398170956ef6fbfc0e1726 sha256: e4672491fb31546b9abb63677f638e738085dc9321398170956ef6fbfc0e1726