This commit is contained in:
Izalia Mae 2022-04-16 06:23:04 -04:00
parent eb2bcf4101
commit 02e78096ab
18 changed files with 329 additions and 272 deletions

View file

@ -6,6 +6,7 @@ from .. import dbus
from .. import __version__ as version
from ..config import var
from ..database import db
from ..exceptions import AccountNotFoundError, NoAccountsError
class Application(Gtk.Application):
@ -28,6 +29,75 @@ class Application(Gtk.Application):
self.connect('startup', self.handle_startup)
def create_tabs(self):
with db.session as s:
for row in s.fetch('tabs', orderby='order'):
self.window.new_tab(row=row)
for url in self.startup_urls:
self.window.new_tab(url, switch=row.active)
if len(self.window.tabdata.keys()) < 1:
self.window.new_tab(None, switch=False)
self.window.startup = False
def get_account_by_handle(self, username, domain=None):
if not len(self.accounts):
raise NoAccountsError('No accounts')
for acct in self.accounts:
if not domain and username == acct.handle:
return acct
elif domain and username == acct.handle and domain == acct.domain:
return acct
raise AccountNotFoundError('Cannot find account')
def get_account_by_id(self, id):
if not len(self.accounts):
raise NoAccountsError('No accounts')
for acct in self.accounts:
if acct.id == id:
return acct
raise AccountNotFoundError('Cannot find account')
def get_default_account(self):
if not len(self.accounts):
raise NoAccountsError('No accounts')
with db.session as s:
default = s.get_config('active_acct')
for acct in self.accounts:
if default == acct.id:
return acct
s.put_config('active_acct', self.accounts[0].id)
return self.accounts[0]
def set_clipboard_text(self, *text):
self.clipboard.set_text(' '.join(text), -1)
def quit(self, *args):
db.unregister_all_callbacks()
if self.window:
#self.window.passwords.db.disconnect()
self.window.handle_window_close()
super().quit()
def handle_activate(self, *args):
self.window = Window(self)
self.dbus = dbus.Server(self.window)
@ -37,6 +107,12 @@ class Application(Gtk.Application):
self.window.show()
def handle_clipboard_clear_password(self, password):
if self.clipboard.wait_for_text() == password:
logging.debug('Clear clipboard text')
self.clipboard.set_text('', 0)
def handle_startup(self, *args):
Gtk.Application.do_startup(self)
accel = Gio.SimpleAction.new('accel', GLib.VariantType.new('s'))
@ -82,79 +158,6 @@ class Application(Gtk.Application):
self.accounts = s.fetch('accounts').all()
def quit(self, *args):
db.unregister_all_callbacks()
if self.window:
#self.window.passwords.db.disconnect()
self.window.handle_window_close()
super().quit()
def create_tabs(self):
with db.session as s:
for row in s.fetch('tabs', orderby='order'):
self.window.new_tab(row=row)
for url in self.startup_urls:
self.window.new_tab(url, switch=row.active)
if len(self.window.tabdata.keys()) < 1:
self.window.new_tab(None, switch=False)
self.window.startup = False
def get_account_by_handle(self, username, domain=None):
if not len(self.accounts):
raise IndexError('No accounts')
for acct in self.accounts:
if not domain and username == acct.handle:
return acct
elif domain and username == acct.handle and domain == acct.domain:
return acct
raise IndexError('Cannot find account')
def get_account_by_id(self, id):
if not len(self.accounts):
raise IndexError('No accounts')
for acct in self.accounts:
if acct.id == id:
return acct
raise IndexError('Cannot find account')
def get_default_account(self):
if not len(self.accounts):
raise IndexError('No accounts')
with db.session as s:
default = s.get_config('active_acct')
for acct in self.accounts:
if default == acct.id:
return acct
return self.accounts[0]
def set_clipboard_text(self, *text):
self.clipboard.set_text(' '.join(text), -1)
def handle_clipboard_clear_password(self, password):
if self.clipboard.wait_for_text() == password:
logging.debug('Clear clipboard text')
self.clipboard.clear()
def handle_accel(self, signal, action):
action = action.get_string()
tab = self.window.active_tab

View file

@ -1,5 +1,6 @@
from .. import fediverse
from ..database import db, default_permissions
from ..exceptions import AccountNotFoundError, NoAccountsError
from ..functions import SignalBlock, connect, get_buffer_text
from ..objects.login_rows import SavedLoginRow
from ..passwords import passdb
@ -8,12 +9,13 @@ from ..passwords import passdb
class StatusBar:
def __init__(self, window):
self.window = window
self.app = window.app
self.siteoptions_handler_ids = []
self.bookmark_row = None
self.theme_enabled = False
self.toot_account = {}
self.toot_acct = None
self.toot_post = None
self.toot_max_len = 500
@ -85,10 +87,10 @@ class StatusBar:
def toot_set_account(self):
with db.session as s:
self.toot_account = s.get_account()
try:
self.toot_account = self.app.get_default_account()
if not self.toot_account:
except NoAccountsError:
self.window.notification('No active fedi accounts', 'error')
return False
@ -171,6 +173,7 @@ class StatusBar:
#self.window.active_tab.editing_action('select')
#self.window.active_tab.editing_action('copy')
self.window.notification('Merp!', 'INFO', 0)
print(self.window.context.get_cookie_manager().delete_cookies_for_domain(self.window.active_tab.url.domain))
#if self.window.themes.current_theme:
#self.window.themes.UnloadTheme()
@ -240,21 +243,21 @@ class StatusBar:
def handle_bookmark_button(self, name):
if name == 'save':
data = self.bookmark_get_data()
with db.session as s:
if name == 'save':
data = self.bookmark_get_data()
with db.session as s:
if self.bookmark_row:
data['id'] = self.bookmark_row.id
s.update_row(self.bookmark_row, **data)
s.put_bookmark(**data)
else:
s.put_bookmark(**data)
elif name == 'delete':
if self.bookmark_row:
s.remove_row(self.bookmark_row)
elif name == 'delete':
if self.bookmark_row:
s.remove_row(self.bookmark_row)
self.window['statusbar-bookmark-popover'].popdown()
self.window.bookmarks.table.refresh()
def handle_fedi_button(self, name):
@ -346,7 +349,7 @@ class StatusBar:
for child in login_list.get_children():
child.destroy()
for row in passdb.fetch(domain=self.window.active_tab.url.domain):
for row in passdb.fetch(domain=self.window.active_tab.url.hostname()):
login_list.add(SavedLoginRow(row, self.window.active_tab.url)['container'])

View file

@ -282,6 +282,11 @@ default_settings = {
'name': 'Serif font',
'description': 'Font to use when the page does not specify a font for pictograph fonts'
},
'user-agent': {
'default': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:99.0) Gecko/20100101 Firefox/99.0',
'name': 'User Agent',
'description': 'How the browser identifies itself when connecting to web servers'
},
'zoom-text-only': {
'default': False,
'name': 'Only zoom text',
@ -302,7 +307,7 @@ class WebSettings(WebKit2.Settings):
super().__init__()
self.tab = tab
self.set_user_agent_with_application_details('pyWeb', version)
#self.set_user_agent_with_application_details('pyWeb', version)
for k,v in default_settings.items():
self[k] = v['default']

View file

@ -88,9 +88,6 @@ var.template.update_env({
logging.set_config('level', var.loglevel)
if var.loglevel in ['DEBUG', 'VERBOSE']:
izzylog.set_config('level', 'VERBOSE')
sys.path.insert(-1, dirs.extensions)
if dirs.data.join('database.sqlite3').exists():

View file

@ -120,7 +120,7 @@ default_config = {
'default_search': ('ddg', 'str'),
'detach_inspector': (False, 'bool'),
'download_dir': (Path('~/Downloads').expanduser(), 'path'),
'enable_autocomplete': (True, 'bool'),
'enable_autocomplete': (False, 'bool'),
'fullscreen': (False, 'bool'),
'homepage': (var.local + '/', 'str'),
'https_force': (True, 'bool'),
@ -334,12 +334,13 @@ class CustomSession(Session):
data = DotDict(
name = name,
url = url,
description = description,
category = category or 'Misc',
lastupdate = datetime.now()
)
if description:
data['description'] = description
return self.insert('bookmarks', **data)

View file

@ -38,11 +38,6 @@ class Search(Row):
class Account(Row):
_api = None
_emojis = None
_db = None
def __run__(self, session):
self._db = session.db
@property
@ -53,6 +48,12 @@ class Account(Row):
return self._api
@property
def active(self):
with self._db.session as s:
return s.get_config('active_acct') == self.id
@property
def avatar(self):
return dirs.avatars.join(f'{self.id}.png')
@ -68,12 +69,6 @@ class Account(Row):
return
@property
def active(self):
with self._db.session as s:
return s.get_config('active_acct') == self.id
@property
def emojis(self):
if not self._emojis:
@ -186,8 +181,3 @@ class Account(Row):
def set_active(self):
with self._db.session as s:
s.put_config('active_acct', self.id)
def test(self):
string = '30+ Transfem Sergal :trans_furr_white: :nbdab: :nbdab:\n\nDoes lots of Python crimes'
return self.replace_emojis(string)

View file

@ -0,0 +1,5 @@
class NoAccountsError(Exception):
'Raise when doing an action that requires a fediverse account, but none exist'
class AccountNotFoundError(Exception):
'Raise when a specific account is not found'

View file

@ -1,38 +1,34 @@
// General
function connect_event(name, signal, callback) {
element = document.getElementById(name);
const element = document.getElementById(name);
element.addEventListener(signal, callback);
}
function delete_item(base_url, id) {
request(`${base_url}/${id}`, function(xhr) {
if (xhr.status != 200) {return;}
request(`${base_url}/${id}`, (response, body) => {
if (response.status != 200) {return;}
var element = document.getElementById(id);
const element = document.getElementById(id);
element.parentElement.removeChild(element);
})
});
}
function request(url, callback, timeout=5) {
const xhr = new XMLHttpRequest();
xhr.timeout = 5
xhr.open('GET', url);
if (callback != undefined) {
xhr.onload = function(event) {
callback(event.target);
function request(url, callback) {
fetch(url).then((response) => {
if (callback != null) {
response.text().then((body) => {
callback(response, body)
});
}
}
xhr.send();
});
}
function toggle_all_details(class_name, state) {
var elements = document.getElementsByClassName(class_name);
const elements = document.getElementsByClassName(class_name);
for (let element of elements) {
if (state && !element.hasAttribute('open')) {
element.setAttribute('open', null);
@ -44,15 +40,15 @@ function toggle_all_details(class_name, state) {
function toggle_menu() {
var menu = document.getElementById('main-menu');
var show_text = menu.hasAttribute('show');
const menu = document.getElementById('main-menu');
const show_text = menu.hasAttribute('show');
if (show_text) {
menu.removeAttribute('show');
} else {
menu.setAttribute('show', null);
}
for (let item of document.getElementsByClassName('menu-item-text')) {
if (show_text) {
item.style.display = 'none'
@ -71,28 +67,24 @@ function handle_key_enter(event) {
function handle_save_config(event) {
var input = event.target;
const input = event.target;
let value = '';
if (input.type.toUpperCase() == 'CHECKBOX') {
if (input.checked) {
var value = 'true';
value = 'true';
} else {
var value = 'false';
value = 'false';
}
} else {
var value = input.value;
value = input.value;
}
const url = new URL(input.form.action);
url.searchParams.set(input.id, value)
request(url, function(xhr) {
if (xhr.status == 200) {
console.log(xhr.status, url);
request(url, (response, body) => {
if (response.status == 200) {
console.log(`Set config: ${input.id}=${value}`);
}
});
@ -102,15 +94,15 @@ function handle_save_config(event) {
// Fediverse
function create_account_nodes(ids) {
for (let id of ids) {
request(`/fediverse/acct_info/${id}`, function(xhr) {
if (xhr.status != 200) {
console.log(`Error %{xhr.status} when trying to fetch account: ${xhr.responseText}`);
request(`/fediverse/acct_info/${id}`, (response, body) => {
if (response.status != 200) {
console.log(`Error ${response.status} when trying to fetch account: ${body}`);
return;
}
const accts = document.getElementById('accounts');
const container = document.createElement('div');
container.innerHTML = xhr.responseText;
container.innerHTML = body;
accts.appendChild(container.children[0]);
})}
@ -118,8 +110,8 @@ function create_account_nodes(ids) {
function set_active(acctid) {
request(`/fediverse/set_active/${acctid}`, function(xhr) {
if (xhr.status != 200) {
request(`/fediverse/set_active/${acctid}`, (response, body) => {
if (response.status != 200) {
console.log(`Failed to set account active: ID ${acctid}`);
return;
}
@ -127,11 +119,10 @@ function set_active(acctid) {
for (let acct of document.getElementsByClassName('account')) {
var active = acct.getElementsByClassName('active')[0];
if (acct.id == `ACCT${acctid}`) {
active.style.display = 'none'
if (acct.id == acctid) {
active.style.display = 'none';
} else {
active.style.display = 'inline-block'
active.style.display = 'inline-block';
}
}
});
@ -140,8 +131,8 @@ function set_active(acctid) {
// History
function delete_history(histid) {
request(`/history/delete/${histid}`, function(xhr) {
if (xhr.status != 200) {return;}
request(`/history/delete/${histid}`, (response, body) => {
if (response.status != 200) {return;}
const element = document.getElementById(histid);
const details = element.parentElement;
@ -157,20 +148,19 @@ function delete_history(histid) {
// Search
function set_default_search(id) {
request(`/search/default/${id}`, function(xhr) {
if (xhr.status != 200) {
request(`/search/default/${id}`, (response, body) => {
if (response.status != 200) {
console.log(`Failed to set search engine active: ID ${id}`);
return;
}
for (let acct of document.getElementsByClassName('search-item')) {
var active = acct.getElementsByClassName('default')[0];
const active = acct.getElementsByClassName('default')[0];
if (acct.id == `SEARCH${id}`) {
active.style.display = 'none'
active.style.display = 'none';
} else {
active.style.display = 'inline-block'
active.style.display = 'inline-block';
}
}
});
@ -179,9 +169,8 @@ function set_default_search(id) {
// Passwords
function copy_password(id) {
console.log(id);
request(`/passwords/copy/${id}`, function(xhr) {
if (xhr.status != 200) {
request(`/passwords/copy/${id}`, (response, body) => {
if (response.status != 200) {
console.log(`Error code when trying to copy password: ${xhr.status} ${xhr.statusText}`);
}
});

View file

@ -9,9 +9,14 @@ class LoginRowBase:
return self.ui.get_object(key)
@property
def app(self):
return Gio.Application.get_default()
@property
def window(self):
return Gio.Application.get_default().window
return self.app.window
def connect(self, name, signal, callback, *args, original_args=False, **kwargs):
@ -25,36 +30,39 @@ class LoginRowBase:
class SavedLoginRow(LoginRowBase):
def __init__(self, row, page_url):
self.ui = Gtk.Builder.new_from_file(dirs.resources.join('password_saved.ui'))
self.passrow = row
self.tab = self.window.active_tab
self.row = row
with db.session as s:
self.dbrow = s.get_passfield(page_url)
self['username'].set_text(self.passrow['username'])
self['username'].set_text(self.row['username'])
if self.passrow.url != page_url or not self.dbrow:
self['fill'].set_sensitive(False)
#if self.row.url != page_url or not self.dbrow:
#self['fill'].set_sensitive(False)
self.connect('fill', 'clicked', self.handle_fill_password)
self.connect('copy', 'clicked', self.handle_copy_password)
self.connect('copy-password', 'clicked', self.handle_copy_password)
self.connect('copy-username', 'clicked', self.row.copy_username)
self['container'].show_all()
def handle_copy_password(self):
password = self.passrow.password
@property
def tab(self):
return self.window.active_tab
self.window.clipboard.set_text(password, -1)
self.window.notification('Copied password to clipboard for 30 seconds')
TimeoutCallback(30, run_in_gui_thread, self.window.passwords.handle_clear_clipboard, self.window.clipboard, password).start()
def handle_copy_password(self):
self.row.copy_password(60)
self.window.notification('Copied password to clipboard for 5 seconds')
self.window['statusbar-logins-popover'].popdown()
def handle_fill_password(self):
self.tab.run_js(f'document.getElementsByName("{self.dbrow.userfield}")[0].value = "{self.passrow.username}"')
self.tab.run_js(f'document.getElementsByName("{self.dbrow.passfield}")[0].value = "{self.passrow.password}"')
with dirs.resources.join('ext_js/autofill.js').open() as fd:
self.tab.run_js(fd.read().replace('USERNAME_VALUE', self.row.username).replace('PASSWORD_VALUE', self.row.password))
self.window['statusbar-logins-popover'].popdown()

View file

@ -4,6 +4,8 @@ from datetime import datetime
from secretstorage.collection import Collection, get_collection_by_alias, create_collection
from secretstorage.exceptions import ItemNotFoundException, LockedException
from .functions import TimeoutCallback, get_app, run_in_gui_thread
pass_store_keys = ['username', 'domain', 'url', 'note']
pass_keys = [*pass_store_keys, 'created', 'modified', 'label', 'password']
@ -274,6 +276,18 @@ class PasswordItem:
return self.update(note=value)
def copy_password(self, timeout=60):
app = get_app()
app.set_clipboard_text(self.password)
timer = TimeoutCallback(timeout, run_in_gui_thread, app.handle_clipboard_clear_password, self.password)
timer.start()
def copy_username(self):
get_app().set_clipboard_text(self.username)
def as_dict(self):
return DotDict(
id = self.id,

View file

@ -178,7 +178,7 @@ def fediverse_refresh(handler, request, acctid):
return request.error(f'Account with ID not found: {acctid}', 404)
row.refresh()
return request.redirect('/fediverse')
return request.ok_or_redirect(f'Refreshed account info: {row.fullhandle}')
@Local.route('/fediverse/set_active/{acctid:int}')
@ -190,8 +190,7 @@ def fediverse_set_active(handler, request, acctid):
return request.error(f'Account with ID not found: {acctid}', 404)
row.set_active()
logging.verbose('Set account as active:', row.fullhandle)
return request.response('OK')
return request.ok_or_redirect(f'Account set as active: {row.fullhandle}')
@Local.route('/fediverse/logout/{acctid:int}')
@ -349,10 +348,7 @@ def passwords_copy(handler, request, rowid):
except KeyError:
return request.error(f'Cannot find password: {rowid}', 404)
handler.app.set_clipboard_text(row.password)
timer = TimeoutCallback(60, run_in_gui_thread, handler.app.handle_clipboard_clear_password, row.password)
timer.start()
row.copy_password()
return request.ok_or_redirect(f'Copied password for 60 seconds')
@ -384,7 +380,7 @@ def preferences_home(handler, request):
@Local.route('/preferences/update')
def preferences_update(handler, request):
if not len(request.query):
if not len([key for key in request.query.keys() if key != 'redir']):
return request.error('No key/value pairs provided', 400)
with db.session as s:
@ -395,7 +391,7 @@ def preferences_update(handler, request):
row = s.put_config(key, value)
logging.verbose(f'Updated config: {row.key} = {row.value}')
return request.ok_or_redirect('/preferences', 'Updated preferences')
return request.ok_or_redirect('Updated preferences')
### Search ###

View file

@ -0,0 +1,28 @@
function fetch_fields() {
var userfield = null;
var passfield = null;
Array.from(document.forms).forEach((form) => {
Array.from(form.getElementsByTagName('input')).forEach((input) => {
if (input.type == 'password') {
passfield = input;
} else if (input.name.includes('user')) {
userfield = input;
}
if (![userfield, passfield].includes(null)) {
return;
}
});
});
return [userfield, passfield];
}
fields = fetch_fields();
if (!fields.includes(null)) {
fields[0].value = 'USERNAME_VALUE';
fields[1].value = 'PASSWORD_VALUE';
}

View file

@ -898,7 +898,7 @@ AND CONDITIONS OF THIS LICENSE.
<property name="icon-name">window-close</property>
</object>
<object class="GtkPopover" id="statusbar-logins-popover">
<property name="width-request">400</property>
<property name="width-request">500</property>
<property name="height-request">400</property>
<property name="can-focus">False</property>
<child>

View file

@ -20,8 +20,22 @@
</packing>
</child>
<child>
<object class="GtkButton" id="copy">
<property name="label" translatable="yes">Copy</property>
<object class="GtkButton" id="copy-username">
<property name="label" translatable="yes">Username</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="tooltip-text" translatable="yes">Copy username to clipboard</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="copy-password">
<property name="label" translatable="yes">Password</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>

View file

@ -49,12 +49,12 @@
"izzylib": {
"version": "0.1.0",
"options": [],
"url": "git+https://git.barkshark.xyz/izaliamae/izzylib_sql"
"url": "git+https://git.barkshark.xyz/izaliamae/izzylib-sql"
},
"izzylib_http_async": {
"version": "0.1.0",
"options": [],
"url": "git+https://git.barkshark.xyz/izaliamae/izzylib_http_async"
"url": "git+https://git.barkshark.xyz/izaliamae/izzylib-http-async"
},
"mastodon.py": {
"version": "1.5.1",
@ -81,5 +81,25 @@
"options": [],
"url": null
}
},
"watcher": {
"path": "barkshark_web",
"command": "barkshark_web",
"env": {"LOG_LEVEL": "VERBOSE"},
"ext": [
"py",
"pyx",
"pyc"
],
"ignore_dirs": [
"build",
"config",
"data"
],
"ignore_files": [
"reload.py",
"test.py",
"pyvenv.py"
]
}
}
}

View file

@ -1,13 +1 @@
izzylib[dbus,http_urllib_client,sql,template] @ git+https://git.barkshark.xyz/izaliamae/izzylib@ab87e880a15b3eb2bb1420b6f169653cc00bfcd6
beautifulsoup4==4.9.3
configobj>=5.0.6
lxml>=4.6.3
mastodon.py==1.5.1
pillow==8.3.2
psutil==5.8.0
pygobject==3.38.0
pysftp==0.2.9
SecretStorage==3.3.1
tldextract==3.1.0
validators==0.18.2
.

58
setup.cfg Normal file
View file

@ -0,0 +1,58 @@
[metadata]
name = Barkshark Web
version = 0.3.8
author = Zoey Mae
author_email = zoey@barkshark.xyz
url = https://git.barkshark.xyz/izaliamae/barkshark-web
description = Python venv manager
long_description = file: README.md
long_description_content_type = text/markdown; charset=UTF-8
license = CNPL 4+
license_file = LICENSE
platform = any
keywords = python development venv
classifiers =
Development Status :: 4 - Beta
Intended Audience :: End Users/Desktop
License :: OSI Approved :: GNU General Public License v3
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Operating System :: POSIX
Operating System :: MacOS :: MacOS X
Operating System :: Microsoft :: Windows
Topic :: Internet :: WWW/HTTP
project_urls =
Bug Tracker = https://git.barkshark.xyz/izaliamae/barkshark-web/issues
Documentation = https://git.barkshark.xyz/izaliamae/barkshark-web/wiki
Source Code = https://git.barkshark.xyz/izaliamae/barkshark-web
[options]
include_package_data = true
python_requires = >= 3.8
packages =
barkshark_web
setup_requires =
izzylib @ git+https://git.barkshark.xyz/izaliamae/izzylib@a156b3b416a9549ee439adc36785cca4131c499c
izzylib_sql @ git+https://git.barkshark.xyz/izaliamae/izzylib-sql@ebfe4fa678f16f35f650afd077a97e4a7cf45d61
izzylib_http_async @ git+https://git.barkshark.xyz/izaliamae/izzylib-http-async@216a779f221e926cd3130404bd33cb916f87d21a
beautifulsoup4==4.9.3
lxml==4.6.3
mastodon.py==1.5.1
pillow==8.3.2
psutil==5.8.0
pygobject==3.38.0
pysftp==0.2.9
SecretStorage==3.3.1
tldextract==3.1.0
validators==0.18.2
[options.entry_points]
console_scripts =
pyvenv = barkshark_web.startup:main
[bdist_wheel]
universal = false
[sdist]
formats = zip, gztar

View file

@ -1,64 +1,2 @@
#!/usr/bin/env python3
import os, shutil, sys
from pathlib import Path
from setuptools import setup, find_packages
scriptpath = Path(__file__).resolve().parent
extsetup = scriptpath.joinpath('webextension/build.sh')
extloader = scriptpath.joinpath('bsweb/bin/pythonloader.so')
extloader_build = scriptpath.joinpath('webextension/pythonloader.so')
with scriptpath.joinpath('requirements.txt').open() as fd:
requirements = [req.replace('\n', '') for req in fd.readlines()]
with scriptpath.joinpath('apt-requirements.txt').open() as fd:
apt_requirements = ' '.join([req.replace('\n', '') for req in fd.readlines()])
#if os.environ.get('APT_INSTALL'):
#os.system(f'sudo apt install {apt_requirements} -y --no-install-recommends')
#extloader.parent.mkdir(exist_ok=True)
#if not extloader.exists():
#os.system(f'cd {scriptpath} && git submodule init')
#os.system(extsetup)
#shutil.copy(extloader_build, extloader)
setup(
name='pyweb',
version='0.3.5',
packages=find_packages(),
entry_points={
'console_scripts': [
'bsweb = bsweb.startup:main'
]
},
python_requires='>=3.8.0',
install_requires=requirements,
include_package_data=True,
author='Zoey Mae',
author_email='admin@barkshark.xyz',
description='Barkshark Web: Simple GTK web browser',
keywords='gtk web browser gui',
url='https://git.barkshark.xyz/izaliamae/pyweb',
project_urls={
'Bug Tracker': 'https://git.barkshark.xyz/izaliamae/pyweb/issues',
'Documentation': 'https://git.barkshark.xyz/izaliamae/pyweb/wiki/Index',
'Source Code': 'https://git.barkshark.xyz/izaliamae/pyweb'
},
classifiers=[
'Development Status :: 4 - Beta',
'Intended Audience :: End Users/Desktop',
'License :: OSI Approved :: GNU General Public License v3',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Operating System :: POSIX',
'Operating System :: MacOS :: MacOS X',
'Operating System :: Microsoft :: Windows',
'Topic :: Internet :: WWW/HTTP'
]
)
import setuptools
setuptools.setup()