Skip to content

Commit

Permalink
Merge pull request #13 from Guts/refacto/apply-git-hooks
Browse files Browse the repository at this point in the history
refacto(plugin): apply git hooks against existing codebase
  • Loading branch information
kannes authored Sep 26, 2024
2 parents c325761 + 7e7344b commit 4207040
Show file tree
Hide file tree
Showing 45 changed files with 780 additions and 422 deletions.
6 changes: 3 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ repos:
- --markdown-linebreak-ext=md

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.5.0"
rev: "v0.6.7"
hooks:
- id: ruff
args:
- --fix-only
- --target-version=py39

- repo: https://github.com/psf/black
rev: 24.4.2
rev: 24.8.0
hooks:
- id: black
args:
Expand All @@ -53,7 +53,7 @@ repos:
- --filter-files

- repo: https://github.com/pycqa/flake8
rev: 7.1.0
rev: 7.1.1
hooks:
- id: flake8
additional_dependencies: ["flake8-qgis"]
Expand Down
1 change: 0 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,3 @@ These are mostly guidelines, not rules. Use your best judgment, and feel free to
We use git hooks through [pre-commit](https://pre-commit.com/) to enforce and automatically check some "rules". Please install them (`pre-commit install`) before to push any commit.

See the relevant configuration file: `.pre-commit-config.yaml`.

1 change: 1 addition & 0 deletions profile_manager/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,5 @@ def classFactory(iface): # pylint: disable=invalid-name
"""
#
from .profile_manager import ProfileManager

return ProfileManager(iface)
11 changes: 6 additions & 5 deletions profile_manager/darkdetect/__init__.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
#-----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
# Copyright (C) 2019 Alberto Sottile
#
# Distributed under the terms of the 3-clause BSD License.
#-----------------------------------------------------------------------------
# -----------------------------------------------------------------------------

__version__ = '0.1.1'
__version__ = "0.1.1"

import sys
import platform
import sys

if sys.platform != "darwin":
from ._dummy import *
else:
from distutils.version import LooseVersion as V

if V(platform.mac_ver()[0]) < V("10.14"):
from ._dummy import *
else:
from ._detect import *
del V

del sys, platform
del sys, platform
44 changes: 25 additions & 19 deletions profile_manager/darkdetect/_detect.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
#-----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
# Copyright (C) 2019 Alberto Sottile
#
# Distributed under the terms of the 3-clause BSD License.
#-----------------------------------------------------------------------------
# -----------------------------------------------------------------------------

import ctypes
import ctypes.util

appkit = ctypes.cdll.LoadLibrary(ctypes.util.find_library('AppKit'))
objc = ctypes.cdll.LoadLibrary(ctypes.util.find_library('objc'))
appkit = ctypes.cdll.LoadLibrary(ctypes.util.find_library("AppKit"))
objc = ctypes.cdll.LoadLibrary(ctypes.util.find_library("objc"))

void_p = ctypes.c_void_p
ull = ctypes.c_uint64
Expand All @@ -20,45 +20,51 @@

msg = objc.objc_msgSend


def _utf8(s):
if not isinstance(s, bytes):
s = s.encode('utf8')
s = s.encode("utf8")
return s


def n(name):
return objc.sel_registerName(_utf8(name))


def C(classname):
return objc.objc_getClass(_utf8(classname))


def theme():
NSAutoreleasePool = objc.objc_getClass('NSAutoreleasePool')
pool = msg(NSAutoreleasePool, n('alloc'))
pool = msg(pool, n('init'))
NSAutoreleasePool = objc.objc_getClass("NSAutoreleasePool")
pool = msg(NSAutoreleasePool, n("alloc"))
pool = msg(pool, n("init"))

NSUserDefaults = C('NSUserDefaults')
stdUserDef = msg(NSUserDefaults, n('standardUserDefaults'))
NSUserDefaults = C("NSUserDefaults")
stdUserDef = msg(NSUserDefaults, n("standardUserDefaults"))

NSString = C('NSString')
NSString = C("NSString")

key = msg(NSString, n("stringWithUTF8String:"), _utf8('AppleInterfaceStyle'))
appearanceNS = msg(stdUserDef, n('stringForKey:'), void_p(key))
appearanceC = msg(appearanceNS, n('UTF8String'))
key = msg(NSString, n("stringWithUTF8String:"), _utf8("AppleInterfaceStyle"))
appearanceNS = msg(stdUserDef, n("stringForKey:"), void_p(key))
appearanceC = msg(appearanceNS, n("UTF8String"))

if appearanceC is not None:
out = ctypes.string_at(appearanceC)
else:
out = None

msg(pool, n('release'))
msg(pool, n("release"))

if out is not None:
return out.decode('utf-8')
return out.decode("utf-8")
else:
return 'Light'
return "Light"


def isDark():
return theme() == 'Dark'
return theme() == "Dark"


def isLight():
return theme() == 'Light'
return theme() == "Light"
11 changes: 7 additions & 4 deletions profile_manager/darkdetect/_dummy.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
#-----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
# Copyright (C) 2019 Alberto Sottile
#
# Distributed under the terms of the 3-clause BSD License.
#-----------------------------------------------------------------------------
# -----------------------------------------------------------------------------


def theme():
return None



def isDark():
return None



def isLight():
return None
Empty file.
26 changes: 18 additions & 8 deletions profile_manager/datasources/Bookmarks/bookmark_handler.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from lxml import etree as et
from pathlib import Path

from lxml import etree as et
from qgis.core import Qgis, QgsMessageLog


Expand All @@ -26,54 +26,64 @@ def import_bookmarks(source_bookmark_file: str, target_bookmark_file: str):
# get the element tree of the source file
QgsMessageLog.logMessage("import_bookmarks", "Profile Manager", level=Qgis.Critical)
try:
source_tree = et.parse(source_bookmark_file, et.XMLParser(remove_blank_text=True))
source_tree = et.parse(
source_bookmark_file, et.XMLParser(remove_blank_text=True)
)

# check if target file exists
create_bookmark_file_if_not_exist(target_bookmark_file)
# get the element tree of the target file
# fill if empty
target_tree = et.parse(target_bookmark_file, et.XMLParser(remove_blank_text=True))
target_tree = et.parse(
target_bookmark_file, et.XMLParser(remove_blank_text=True)
)

# find all bookmark elements
source_root_tag = source_tree.findall('Bookmark')
source_root_tag = source_tree.findall("Bookmark")

# get the root element "Bookmarks"
target_tree_root = target_tree.getroot()

# Remove duplicate entries to prevent piling data
target_tree_root = remove_duplicates(source_root_tag, target_tree, target_tree_root)
target_tree_root = remove_duplicates(
source_root_tag, target_tree, target_tree_root
)

# append the elements
for element in source_root_tag:
target_tree_root.append(element)

# overwrite the xml file
et.ElementTree(target_tree_root).write(
target_bookmark_file, pretty_print=True, encoding='utf-8', xml_declaration=True
target_bookmark_file,
pretty_print=True,
encoding="utf-8",
xml_declaration=True,
)
except et.Error as e:
# TODO: It would be nice to have a smaller and more specific try block but until then we except broadly
error = f"{type(e)}: {str(e)}"
QgsMessageLog.logMessage(error, "Profile Manager", level=Qgis.Warning)
return error


def remove_duplicates(source_root_tag, target_tree, target_tree_root):
"""Removes bookmarks from target that exist in the (to be imported) source too."""
# TODO FIXME this only checks the name of the bookmarks which will lead to false positives
# it is ok and supported by QGIS to have the same name for multiple bookmarks
# TODO compare the complete content of the xml node!
target_root_tag = target_tree.findall('Bookmark')
target_root_tag = target_tree.findall("Bookmark")
for s_element in source_root_tag:
for t_element in target_root_tag:
if s_element.attrib["name"] == t_element.attrib["name"]:
target_tree_root.remove(t_element)

return target_tree_root


def create_bookmark_file_if_not_exist(bookmark_file):
"""Checks if file exists and creates it if not"""
target_file = Path(bookmark_file)
if not target_file.is_file():
with open(bookmark_file, "w") as new_file:
new_file.write("<Bookmarks></Bookmarks>")

Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from os import path
from shutil import copy2

from ...utils import adjust_to_operating_system
from profile_manager.utils import adjust_to_operating_system


def import_customizations(source_profile_path: str, target_profile_path: str):
Expand All @@ -22,22 +22,30 @@ def import_customizations(source_profile_path: str, target_profile_path: str):
TODO
"""
# Copy (overwrite) the QGISCUSTOMIZATION3.ini if exist
source_customini_path = adjust_to_operating_system(source_profile_path + "QGIS/QGISCUSTOMIZATION3.ini")
target_customini_path = adjust_to_operating_system(target_profile_path + "QGIS/QGISCUSTOMIZATION3.ini")
source_customini_path = adjust_to_operating_system(
source_profile_path + "QGIS/QGISCUSTOMIZATION3.ini"
)
target_customini_path = adjust_to_operating_system(
target_profile_path + "QGIS/QGISCUSTOMIZATION3.ini"
)
if path.exists(source_customini_path):
copy2(source_customini_path, target_customini_path)

# Copy [UI] section from QGIS3.ini
source_qgis3ini_path = adjust_to_operating_system(source_profile_path + "QGIS/QGIS3.ini")
target_qgis3ini_path = adjust_to_operating_system(target_profile_path + "QGIS/QGIS3.ini")
source_qgis3ini_path = adjust_to_operating_system(
source_profile_path + "QGIS/QGIS3.ini"
)
target_qgis3ini_path = adjust_to_operating_system(
target_profile_path + "QGIS/QGIS3.ini"
)

source_ini_parser = RawConfigParser()
source_ini_parser.optionxform = str # str = case-sensitive option names
source_ini_parser.read(source_qgis3ini_path)

# TODO this is broken, right? It looks for [UI] but even in QGIS 3.10 (didnt check older) the (single) section is named [Customization]
if source_ini_parser.has_section('UI'):
ui_data = dict(source_ini_parser.items('UI'))
if source_ini_parser.has_section("UI"):
ui_data = dict(source_ini_parser.items("UI"))

target_ini_parser = RawConfigParser()
target_ini_parser.optionxform = str # str = case-sensitive option names
Expand All @@ -49,6 +57,5 @@ def import_customizations(source_profile_path: str, target_profile_path: str):

target_ini_parser.set("UI", setting, ui_data[setting])

with open(target_qgis3ini_path, 'w') as qgisconf:
with open(target_qgis3ini_path, "w") as qgisconf:
target_ini_parser.write(qgisconf, space_around_delimiters=False)

Empty file.
Loading

0 comments on commit 4207040

Please sign in to comment.