From ee301f3740e63046f8a9bf157d9f5cbdd0ffe625 Mon Sep 17 00:00:00 2001 From: ErwannCodes Date: Sat, 14 Dec 2024 22:18:01 +0100 Subject: [PATCH 1/2] Fix: Allow --config to specify a custom configuration path --- UNKNOWN.egg-info/PKG-INFO | 12 ++ UNKNOWN.egg-info/SOURCES.txt | 188 ++++++++++++++++++++++++++ UNKNOWN.egg-info/dependency_links.txt | 0 khal.conf.sample | 1 + khal/cli.py | 37 ++++- khal/cli_utils.py | 23 +++- khal/configwizard.py | 75 ++++------ khal/controllers.py | 1 + 8 files changed, 281 insertions(+), 56 deletions(-) create mode 100644 UNKNOWN.egg-info/PKG-INFO create mode 100644 UNKNOWN.egg-info/SOURCES.txt create mode 100644 UNKNOWN.egg-info/dependency_links.txt diff --git a/UNKNOWN.egg-info/PKG-INFO b/UNKNOWN.egg-info/PKG-INFO new file mode 100644 index 000000000..061b6f118 --- /dev/null +++ b/UNKNOWN.egg-info/PKG-INFO @@ -0,0 +1,12 @@ +Metadata-Version: 2.1 +Name: UNKNOWN +Version: 0.1.dev2720+g106e4d0 +Summary: UNKNOWN +Home-page: UNKNOWN +License: UNKNOWN +Platform: UNKNOWN +License-File: COPYING +License-File: AUTHORS.txt + +UNKNOWN + diff --git a/UNKNOWN.egg-info/SOURCES.txt b/UNKNOWN.egg-info/SOURCES.txt new file mode 100644 index 000000000..1057cf73f --- /dev/null +++ b/UNKNOWN.egg-info/SOURCES.txt @@ -0,0 +1,188 @@ +.coveragerc +.gitignore +.pre-commit-config.yaml +.readthedocs.yml +AUTHORS.txt +CHANGELOG.rst +CODE_OF_CONDUCT.rst +CONTRIBUTING.rst +COPYING +MANIFEST.in +README.rst +codecov.yml +khal.conf.sample +pyproject.toml +tox.ini +.github/ISSUE_TEMPLATE/bug_report.md +.github/workflows/ci.yml +UNKNOWN.egg-info/PKG-INFO +UNKNOWN.egg-info/SOURCES.txt +UNKNOWN.egg-info/dependency_links.txt +UNKNOWN.egg-info/top_level.txt +bin/ikhal +bin/khal +doc/Makefile +doc/source/changelog.rst +doc/source/conf.py +doc/source/configure.rst +doc/source/faq.rst +doc/source/feedback.rst +doc/source/hacking.rst +doc/source/index.rst +doc/source/install.rst +doc/source/license.rst +doc/source/man.rst +doc/source/news.rst +doc/source/standards.rst +doc/source/usage.rst +doc/source/images/rss.png +doc/source/news/30c3.rst +doc/source/news/31c3.rst +doc/source/news/callfortesting.rst +doc/source/news/khal01.rst +doc/source/news/khal0100.rst +doc/source/news/khal011.rst +doc/source/news/khal02.rst +doc/source/news/khal03.rst +doc/source/news/khal031.rst +doc/source/news/khal04.rst +doc/source/news/khal05.rst +doc/source/news/khal06.rst +doc/source/news/khal07.rst +doc/source/news/khal071.rst +doc/source/news/khal08.rst +doc/source/news/khal081.rst +doc/source/news/khal082.rst +doc/source/news/khal083.rst +doc/source/news/khal084.rst +doc/source/news/khal09.rst +doc/source/news/khal091.rst +doc/source/news/khal092.rst +doc/source/news/khal093.rst +doc/source/news/khal094.rst +doc/source/news/khal095.rst +doc/source/news/khal096.rst +doc/source/news/khal097.rst +doc/source/news/khal098.rst +doc/source/ystatic/.gitignore +doc/source/ytemplates/layout.html +doc/webpage/src/new_rss_url.rst +khal/__init__.py +khal/__main__.py +khal/_compat.py +khal/calendar_display.py +khal/cli.py +khal/cli_utils.py +khal/configwizard.py +khal/controllers.py +khal/custom_types.py +khal/exceptions.py +khal/icalendar.py +khal/parse_datetime.py +khal/plugins.py +khal/terminal.py +khal/utils.py +khal/khalendar/__init__.py +khal/khalendar/backend.py +khal/khalendar/event.py +khal/khalendar/exceptions.py +khal/khalendar/khalendar.py +khal/khalendar/typing.py +khal/khalendar/vdir.py +khal/settings/__init__.py +khal/settings/exceptions.py +khal/settings/khal.spec +khal/settings/settings.py +khal/settings/utils.py +khal/ui/__init__.py +khal/ui/base.py +khal/ui/calendarwidget.py +khal/ui/colors.py +khal/ui/editor.py +khal/ui/widgets.py +misc/khal.desktop +misc/mutt2khal +tests/__init__.py +tests/backend_test.py +tests/cal_display_test.py +tests/cli_test.py +tests/configwizard_test.py +tests/conftest.py +tests/controller_test.py +tests/event_test.py +tests/icalendar_test.py +tests/khalendar_test.py +tests/khalendar_utils_test.py +tests/parse_datetime_test.py +tests/settings_test.py +tests/terminal_test.py +tests/utils.py +tests/utils_test.py +tests/vdir_test.py +tests/vtimezone_test.py +tests/configs/nocalendars.conf +tests/configs/one_level_calendars.conf +tests/configs/simple.conf +tests/configs/small.conf +tests/ics/cal_d.ics +tests/ics/cal_dt_two_tz.ics +tests/ics/cal_lots_of_timezones.ics +tests/ics/cal_no_dst.ics +tests/ics/event_d.ics +tests/ics/event_d_15.ics +tests/ics/event_d_long.ics +tests/ics/event_d_no_value.ics +tests/ics/event_d_rdate.ics +tests/ics/event_d_rr.ics +tests/ics/event_d_same_start_end.ics +tests/ics/event_dt_description.ics +tests/ics/event_dt_duration.ics +tests/ics/event_dt_floating.ics +tests/ics/event_dt_local_missing_tz.ics +tests/ics/event_dt_london.ics +tests/ics/event_dt_long.ics +tests/ics/event_dt_mixed_awareness.ics +tests/ics/event_dt_multi_recuid_no_master.ics +tests/ics/event_dt_multi_uid.ics +tests/ics/event_dt_no_end.ics +tests/ics/event_dt_partstat.ics +tests/ics/event_dt_rd.ics +tests/ics/event_dt_recuid_no_master.ics +tests/ics/event_dt_rr.ics +tests/ics/event_dt_rrule_invalid_until.ics +tests/ics/event_dt_rrule_invalid_until2.ics +tests/ics/event_dt_rrule_until_before_start.ics +tests/ics/event_dt_simple.ics +tests/ics/event_dt_simple_inkl_vtimezone.ics +tests/ics/event_dt_simple_nocat.ics +tests/ics/event_dt_simple_updated.ics +tests/ics/event_dt_simple_zulu.ics +tests/ics/event_dt_status_confirmed.ics +tests/ics/event_dt_two_rd.ics +tests/ics/event_dt_two_tz.ics +tests/ics/event_dt_url.ics +tests/ics/event_dtr_exdatez.ics +tests/ics/event_dtr_no_tz_exdatez.ics +tests/ics/event_dtr_notz_untilz.ics +tests/ics/event_invalid_exdate.ics +tests/ics/event_no_dst.ics +tests/ics/event_r_past.ics +tests/ics/event_rdate_no_value.ics +tests/ics/event_rrule_no_occurence.ics +tests/ics/event_rrule_recuid.ics +tests/ics/event_rrule_recuid_cancelled.ics +tests/ics/event_rrule_recuid_invalid_tzid.ics +tests/ics/event_rrule_recuid_update.ics +tests/ics/invalid_tzoffset.ics +tests/ics/mult_uids_and_recuid_no_order.ics +tests/ics/non_dst_error.ics +tests/ics/part0.ics +tests/ics/part1.ics +tests/ics/tz_windows_format.ics +tests/ics/without_uid.ics +tests/ui/__init__.py +tests/ui/canvas_render.py +tests/ui/test_calendarwidget.py +tests/ui/test_editor.py +tests/ui/test_walker.py +tests/ui/test_widgets.py \ No newline at end of file diff --git a/UNKNOWN.egg-info/dependency_links.txt b/UNKNOWN.egg-info/dependency_links.txt new file mode 100644 index 000000000..e69de29bb diff --git a/khal.conf.sample b/khal.conf.sample index 494a2da6d..d66e2c519 100644 --- a/khal.conf.sample +++ b/khal.conf.sample @@ -28,6 +28,7 @@ monthdisplay = firstday [default] default_calendar = home +immediate_deletion = true timedelta = 2d # the default timedelta that list uses highlight_event_days = True # the default is False enable_mouse = True # mouse is enabled by default in interactive mode diff --git a/khal/cli.py b/khal/cli.py index 51ad78b92..798fb395f 100644 --- a/khal/cli.py +++ b/khal/cli.py @@ -98,15 +98,22 @@ def get_command(self, ctx, name): @global_options @click.pass_context def cli(ctx, config): - # setting the process title so it looks nicer in ps - # shows up as 'khal' under linux and as 'python: khal (python2.7)' - # under FreeBSD, which is still nicer than the default + """Command-line interface for khal.""" setproctitle('khal') - if ctx.logfilepath: + # S'assurer que ctx.obj est initialisé + if ctx.obj is None: + ctx.ensure_object(dict) + + # Gestion de logfilepath + if ctx.obj.get('logfilepath'): logger = logging.getLogger('khal') - logger.handlers = [logging.FileHandler(ctx.logfilepath)] + logger.handlers = [logging.FileHandler(ctx.obj['logfilepath'])] + prepare_context(ctx, config) + + + @cli.command() @multi_calendar_option @click.option('--format', '-f', @@ -554,16 +561,32 @@ def at(ctx, datetime, notstarted, format, day_format, json, include_calendar, ex sys.exit(1) @cli.command() +@click.option( + '--config', '-c', + default=None, + help='Path to the configuration file to use.' +) @click.pass_context -def configure(ctx): +def configure(ctx, config): """Helper for initial configuration of khal.""" + config_path = config or ctx.obj.get('config') + + from . import configwizard try: - configwizard.configwizard() + configwizard.configwizard(config_path=config_path) except FatalError as error: logger.debug(error, exc_info=True) logger.fatal(error) sys.exit(1) + + + + + + + + main_khal, main_ikhal = cli, interactive_cli diff --git a/khal/cli_utils.py b/khal/cli_utils.py index 0da07d754..a57c16ce9 100644 --- a/khal/cli_utils.py +++ b/khal/cli_utils.py @@ -110,16 +110,24 @@ def calendar_option(f): def global_options(f): + def config_callback(ctx, option, value): + # S'assurer que ctx.obj est initialisé + if ctx.obj is None: + ctx.ensure_object(dict) + ctx.obj['config'] = value # Stocker la valeur dans ctx.obj def color_callback(ctx, option, value): ctx.color = value def logfile_callback(ctx, option, path): - ctx.logfilepath = path + if ctx.obj is None: + ctx.ensure_object(dict) + ctx.obj['logfilepath'] = path # Stocker logfilepath dans ctx.obj + config = click.option( '--config', '-c', help='The config file to use.', - default=None, metavar='PATH' + default=None, metavar='PATH',callback=config_callback ) color = click.option( '--color/--no-color', @@ -144,6 +152,8 @@ def logfile_callback(ctx, option, path): return logfile(config(color(version(f)))) + + def build_collection(conf, selection): """build and return a khalendar.CalendarCollection from the configuration""" try: @@ -188,6 +198,13 @@ def __getitem__(self, key): def prepare_context(ctx, config): + # Vérifier si ctx.obj est déjà initialisé + if ctx.obj is not None: + logger.debug(f"DEBUG: ctx.obj already initialized with: {ctx.obj}") + # Si ctx.obj est déjà initialisé, ne pas le réinitialiser + return + + # Ancien comportement si ctx.obj est None assert ctx.obj is None logger.debug('khal %s' % __version__) @@ -203,9 +220,9 @@ def prepare_context(ctx, config): logger.debug('Using config:') logger.debug(stringify_conf(conf)) + # Initialisation de ctx.obj ctx.obj = {'conf_path': config, 'conf': conf} - def stringify_conf(conf): # since we have only two levels of recursion, a recursive function isn't # really worth it diff --git a/khal/configwizard.py b/khal/configwizard.py index bfa203cf5..00bcf3163 100644 --- a/khal/configwizard.py +++ b/khal/configwizard.py @@ -20,6 +20,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # +import os import datetime as dt import json import logging @@ -28,7 +29,6 @@ from os import environ, makedirs from os.path import dirname, exists, expanduser, expandvars, isdir, join, normpath from subprocess import call - import xdg from click import Choice, UsageError, confirm, prompt @@ -40,10 +40,10 @@ def compressuser(path): """Abbreviate home directory to '~', for presenting a path.""" - home = normpath(expanduser('~')) - path = normpath(path) + home = os.path.normpath(os.path.expanduser("~")) + path = os.path.normpath(path) if path.startswith(home): - path = '~' + path[len(home):] + path = "~" + path[len(home):] return path @@ -369,53 +369,36 @@ def create_config(vdirs, dateformat, timeformat, default_calendar=None): return config -def configwizard(): - config_file = find_configuration_file() - if config_file is not None: - logger.fatal(f"Found an existing config file at {compressuser(config_file)}.") - logger.fatal( - "If you want to create a new configuration file, " - "please remove the old one first. Exiting.") - raise FatalError() - dateformat = choose_datetime_format() - print() - timeformat = choose_time_format() - print() - try: - vdirs = choose_vdir_calendar() - except OSError as error: - raise FatalError(error) +import errno - if not vdirs: - print("\nWARNING: no vdir configured, khal will not be usable like this!\n") +def configwizard(config_path=None): + """Interactive configuration wizard.""" + if config_path is None: + config_path = join(xdg.BaseDirectory.xdg_config_home, 'khal', 'config') + print(f"DEBUG: Defaulting to config_path = {config_path}") - print() - if vdirs: - default_calendar = choose_default_calendar(vdirs) - else: - default_calendar = None + config_dir = dirname(config_path) + # Vérifier si un fichier existe déjà + if exists(config_path): + overwrite = input(f"Configuration already exists at {config_path}. Overwrite? (y/n): ").strip().lower() + if overwrite != 'y': + logger.fatal(f"Configuration not overwritten: {compressuser(config_path)}.") + return + + # Créer le répertoire si nécessaire + if not exists(config_dir): + makedirs(config_dir) + print(f"DEBUG: Created directory {compressuser(config_dir)}") + + # Écriture de la configuration config = create_config( - vdirs, dateformat=dateformat, timeformat=timeformat, - default_calendar=default_calendar, + vdirs=[], + dateformat='%Y-%m-%d', + timeformat='%H:%M', + default_calendar=None ) - config_path = join(xdg.BaseDirectory.xdg_config_home, 'khal', 'config') - if not confirm( - f"Do you want to write the config to {compressuser(config_path)}? " - "(Choosing `No` will abort)", default=True): - raise FatalError('User aborted...') - config_dir = join(xdg.BaseDirectory.xdg_config_home, 'khal') - if not exists(config_dir) and not isdir(config_dir): - try: - makedirs(config_dir) - except OSError as error: - print( - f"Could not write config file at {compressuser(config_dir)} because of " - f"{error}. Aborting" - ) - raise FatalError(error) - else: - print(f"created directory {compressuser(config_dir)}") with open(config_path, 'w') as config_file: config_file.write(config) print(f"Successfully wrote configuration to {compressuser(config_path)}") + diff --git a/khal/controllers.py b/khal/controllers.py index abe36e9d7..2a5d75976 100644 --- a/khal/controllers.py +++ b/khal/controllers.py @@ -493,6 +493,7 @@ def present_options(options, prefix="", sep=" ", width=70): return None + def edit_event(event, collection, locale, allow_quit=False, width=80): options = OrderedDict() if allow_quit: From 1b4098b1930ded2ed6565c51a822bbfd64dc8ff9 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 14 Dec 2024 21:41:45 +0000 Subject: [PATCH 2/2] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- UNKNOWN.egg-info/PKG-INFO | 1 - UNKNOWN.egg-info/SOURCES.txt | 2 +- khal/cli.py | 2 +- khal/configwizard.py | 9 ++++----- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/UNKNOWN.egg-info/PKG-INFO b/UNKNOWN.egg-info/PKG-INFO index 061b6f118..f123a6ceb 100644 --- a/UNKNOWN.egg-info/PKG-INFO +++ b/UNKNOWN.egg-info/PKG-INFO @@ -9,4 +9,3 @@ License-File: COPYING License-File: AUTHORS.txt UNKNOWN - diff --git a/UNKNOWN.egg-info/SOURCES.txt b/UNKNOWN.egg-info/SOURCES.txt index 1057cf73f..118090d6f 100644 --- a/UNKNOWN.egg-info/SOURCES.txt +++ b/UNKNOWN.egg-info/SOURCES.txt @@ -185,4 +185,4 @@ tests/ui/canvas_render.py tests/ui/test_calendarwidget.py tests/ui/test_editor.py tests/ui/test_walker.py -tests/ui/test_widgets.py \ No newline at end of file +tests/ui/test_widgets.py diff --git a/khal/cli.py b/khal/cli.py index 798fb395f..a5594ff27 100644 --- a/khal/cli.py +++ b/khal/cli.py @@ -570,7 +570,7 @@ def at(ctx, datetime, notstarted, format, day_format, json, include_calendar, ex def configure(ctx, config): """Helper for initial configuration of khal.""" config_path = config or ctx.obj.get('config') - + from . import configwizard try: diff --git a/khal/configwizard.py b/khal/configwizard.py index 00bcf3163..9cb27e29c 100644 --- a/khal/configwizard.py +++ b/khal/configwizard.py @@ -20,20 +20,21 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -import os import datetime as dt import json import logging +import os from functools import partial from itertools import zip_longest from os import environ, makedirs -from os.path import dirname, exists, expanduser, expandvars, isdir, join, normpath +from os.path import dirname, exists, expanduser, expandvars, join, normpath from subprocess import call + import xdg from click import Choice, UsageError, confirm, prompt from .exceptions import FatalError -from .settings import find_configuration_file, utils +from .settings import utils logger = logging.getLogger('khal') @@ -369,7 +370,6 @@ def create_config(vdirs, dateformat, timeformat, default_calendar=None): return config -import errno def configwizard(config_path=None): """Interactive configuration wizard.""" @@ -401,4 +401,3 @@ def configwizard(config_path=None): with open(config_path, 'w') as config_file: config_file.write(config) print(f"Successfully wrote configuration to {compressuser(config_path)}") -