icalcli 1.0.5__tar.gz → 1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. {icalcli-1.0.5 → icalcli-1.1}/PKG-INFO +50 -4
  2. icalcli-1.0.5/icalcli.egg-info/PKG-INFO → icalcli-1.1/README.md +43 -19
  3. {icalcli-1.0.5 → icalcli-1.1}/icalcli/__init__.py +3 -1
  4. icalcli-1.1/icalcli/etesync_backend/etebase_crud.py +137 -0
  5. icalcli-1.1/icalcli/etesync_backend/etebase_interface.py +94 -0
  6. {icalcli-1.0.5 → icalcli-1.1}/icalcli/etesync_backend/etesync_crud.py +3 -0
  7. {icalcli-1.0.5 → icalcli-1.1}/icalcli/etesync_backend/etesync_interface.py +5 -0
  8. {icalcli-1.0.5 → icalcli-1.1}/icalcli/file_backend/ics_interface.py +4 -4
  9. {icalcli-1.0.5 → icalcli-1.1}/icalcli/icalcli.py +10 -10
  10. icalcli-1.0.5/README.md → icalcli-1.1/icalcli.egg-info/PKG-INFO +65 -2
  11. {icalcli-1.0.5 → icalcli-1.1}/icalcli.egg-info/SOURCES.txt +2 -3
  12. {icalcli-1.0.5 → icalcli-1.1}/setup.py +1 -1
  13. icalcli-1.0.5/CHANGELOG.md +0 -45
  14. icalcli-1.0.5/exclude +0 -7
  15. icalcli-1.0.5/update-github.md +0 -33
  16. {icalcli-1.0.5 → icalcli-1.1}/LICENSE +0 -0
  17. {icalcli-1.0.5 → icalcli-1.1}/icalcli/argparsers.py +0 -0
  18. {icalcli-1.0.5 → icalcli-1.1}/icalcli/etesync_backend/__init__.py +0 -0
  19. {icalcli-1.0.5 → icalcli-1.1}/icalcli/file_backend/__init__.py +0 -0
  20. {icalcli-1.0.5 → icalcli-1.1}/icalcli/printer.py +0 -0
  21. {icalcli-1.0.5 → icalcli-1.1}/icalcli/utils.py +0 -0
  22. {icalcli-1.0.5 → icalcli-1.1}/icalcli.egg-info/dependency_links.txt +0 -0
  23. {icalcli-1.0.5 → icalcli-1.1}/icalcli.egg-info/entry_points.txt +0 -0
  24. {icalcli-1.0.5 → icalcli-1.1}/icalcli.egg-info/requires.txt +0 -0
  25. {icalcli-1.0.5 → icalcli-1.1}/icalcli.egg-info/top_level.txt +0 -0
  26. {icalcli-1.0.5 → icalcli-1.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: icalcli
3
- Version: 1.0.5
3
+ Version: 1.1
4
4
  Summary: Icalendar Calendar Command Line Interface
5
5
  Home-page: https://github.com/jrvarma/icalcli
6
6
  Maintainer: Jayanth R. Varma
@@ -12,8 +12,13 @@ Classifier: License :: OSI Approved :: MIT License
12
12
  Classifier: Programming Language :: Python :: 3
13
13
  Requires-Python: >=3.6
14
14
  Description-Content-Type: text/markdown
15
- Provides-Extra: parsedatetime
16
15
  License-File: LICENSE
16
+ Requires-Dist: python-dateutil
17
+ Requires-Dist: parsedatetime
18
+ Requires-Dist: icalendar
19
+ Requires-Dist: recurring_ical_events
20
+ Provides-Extra: parsedatetime
21
+ Requires-Dist: parsedatetime; extra == "parsedatetime"
17
22
 
18
23
  # icalcli
19
24
 
@@ -23,7 +28,7 @@ License-File: LICENSE
23
28
 
24
29
  Unlike [gcalcli](https://github.com/insanum/gcalcli) which is tied to Google Calendar, `icalcli` is agnostic to (abstracts away from) the actual backend calendar service. It relies on a backend interface which interacts with the backend calendar to perform all the CRUD (Create, Retrieve, Update and Delete) operations on the actual calendar. The package includes two backends:
25
30
 
26
- * The `etesync_backend` subpackage provides a backend interface to the [EteSync](https://www.etesync.com/) calendar. In fact, `icalcli` was created primarily to provide a command line interface to my self hosted `EteSync` calendar.
31
+ * The `etesync_backend` subpackage provides a backend interface to the [EteSync](https://www.etesync.com/) calendar (versions 1.0 and 2.0). In fact, `icalcli` was created primarily to provide a command line interface to my self hosted `EteSync` calendar.
27
32
 
28
33
  * The `file_backend` subpackage provides a backend interface to a calendar contained in a local `ics` file. This is useful as a viewer/editor of `ics` files. It is also useful to try out `icalci` without having any other backend configured.
29
34
 
@@ -50,6 +55,12 @@ The two included backends would also be useful to those who wish to write their
50
55
  pip install icalcli
51
56
  ```
52
57
 
58
+ or via `pipx`:
59
+
60
+ ```sh
61
+ pipx install icalcli
62
+ ```
63
+
53
64
  ### Install from source
54
65
 
55
66
  ```sh
@@ -57,6 +68,13 @@ git clone https://github.com/jrvarma/icalcli.git
57
68
  cd icalcli
58
69
  python setup.py install
59
70
  ```
71
+
72
+ or via `pipx`:
73
+
74
+ ```sh
75
+ pipx install . --editable
76
+ ```
77
+
60
78
  ## Usage
61
79
 
62
80
  ### Command line arguments
@@ -97,7 +115,7 @@ backend_interface = ICSInterface(["/path/to/ics-file-1", "/path/to/ics-file-2"])
97
115
 
98
116
  ```
99
117
 
100
- #### Example configuration for etesync_backend
118
+ #### Example configuration for etesync_backend (etesync 1.0)
101
119
 
102
120
  This configuration assumes that all the credentials are stored in a plain text (`json`) file. In practice, you would use a more secure storage (perhaps, the `Gnome keyring`) or just read it from the terminal.
103
121
 
@@ -116,6 +134,34 @@ backend_interface = EtesyncInterface(
116
134
  ```
117
135
  See the [Example code](https://github.com/jrvarma/icalcli/issues/1#issuecomment-979851222) for getting the `uid` and `authToken` for the `etesync` calendar.
118
136
 
137
+ #### Example configuration for etebase_backend (etesync 2.0)
138
+
139
+ This configuration assumes that all the credentials are stored in a plain text (`json`) file. In practice, you would use a more secure storage (perhaps, the `Gnome keyring`) or just read it from the terminal.
140
+
141
+ ```
142
+ from icalcli import EtebaseInterface
143
+ import json
144
+
145
+ conf_file = '/path/to/json-file'
146
+ with open(conf_file, 'r') as fp:
147
+ c = json.load(fp)
148
+
149
+ backend_interface = EtebaseInterface(c['user'], c['server_url'], c['password'],
150
+ c['calendar_uid'], silent=False)
151
+ ```
152
+
153
+ The `calendar_uid` can be obtained using the following code. This code assumes that the `dict c` has been populated with the credentials from the `json` file as above.
154
+
155
+ ```
156
+ from etebase import Client, Account, FetchOptions
157
+
158
+ client = Client(c['user'], c['server_url'])
159
+ etebase = Account.login(client, c['user'], c['password'])
160
+ col_mgr = etebase.get_collection_manager()
161
+ print({col.uid: col.meta
162
+ for col in col_mgr.list("etebase.vevent").data})
163
+ ```
164
+
119
165
  ## Recurring events and default search period
120
166
 
121
167
  `icalcli` understands the `RRULE`, `RDATE`, `EXRULE`, `EXDATE` elements of the `icalendar` specification. These elements can be added while creating or editing events using `--rrule`, `--rdate`, `--exrule` and `--exdate` options.
@@ -1,20 +1,3 @@
1
- Metadata-Version: 2.1
2
- Name: icalcli
3
- Version: 1.0.5
4
- Summary: Icalendar Calendar Command Line Interface
5
- Home-page: https://github.com/jrvarma/icalcli
6
- Maintainer: Jayanth R. Varma
7
- Maintainer-email: jrvarma@gmail.com
8
- Classifier: Development Status :: 3 - Alpha
9
- Classifier: Environment :: Console
10
- Classifier: Intended Audience :: End Users/Desktop
11
- Classifier: License :: OSI Approved :: MIT License
12
- Classifier: Programming Language :: Python :: 3
13
- Requires-Python: >=3.6
14
- Description-Content-Type: text/markdown
15
- Provides-Extra: parsedatetime
16
- License-File: LICENSE
17
-
18
1
  # icalcli
19
2
 
20
3
  ### An iCalendar Command Line Interface
@@ -23,7 +6,7 @@ License-File: LICENSE
23
6
 
24
7
  Unlike [gcalcli](https://github.com/insanum/gcalcli) which is tied to Google Calendar, `icalcli` is agnostic to (abstracts away from) the actual backend calendar service. It relies on a backend interface which interacts with the backend calendar to perform all the CRUD (Create, Retrieve, Update and Delete) operations on the actual calendar. The package includes two backends:
25
8
 
26
- * The `etesync_backend` subpackage provides a backend interface to the [EteSync](https://www.etesync.com/) calendar. In fact, `icalcli` was created primarily to provide a command line interface to my self hosted `EteSync` calendar.
9
+ * The `etesync_backend` subpackage provides a backend interface to the [EteSync](https://www.etesync.com/) calendar (versions 1.0 and 2.0). In fact, `icalcli` was created primarily to provide a command line interface to my self hosted `EteSync` calendar.
27
10
 
28
11
  * The `file_backend` subpackage provides a backend interface to a calendar contained in a local `ics` file. This is useful as a viewer/editor of `ics` files. It is also useful to try out `icalci` without having any other backend configured.
29
12
 
@@ -50,6 +33,12 @@ The two included backends would also be useful to those who wish to write their
50
33
  pip install icalcli
51
34
  ```
52
35
 
36
+ or via `pipx`:
37
+
38
+ ```sh
39
+ pipx install icalcli
40
+ ```
41
+
53
42
  ### Install from source
54
43
 
55
44
  ```sh
@@ -57,6 +46,13 @@ git clone https://github.com/jrvarma/icalcli.git
57
46
  cd icalcli
58
47
  python setup.py install
59
48
  ```
49
+
50
+ or via `pipx`:
51
+
52
+ ```sh
53
+ pipx install . --editable
54
+ ```
55
+
60
56
  ## Usage
61
57
 
62
58
  ### Command line arguments
@@ -97,7 +93,7 @@ backend_interface = ICSInterface(["/path/to/ics-file-1", "/path/to/ics-file-2"])
97
93
 
98
94
  ```
99
95
 
100
- #### Example configuration for etesync_backend
96
+ #### Example configuration for etesync_backend (etesync 1.0)
101
97
 
102
98
  This configuration assumes that all the credentials are stored in a plain text (`json`) file. In practice, you would use a more secure storage (perhaps, the `Gnome keyring`) or just read it from the terminal.
103
99
 
@@ -116,6 +112,34 @@ backend_interface = EtesyncInterface(
116
112
  ```
117
113
  See the [Example code](https://github.com/jrvarma/icalcli/issues/1#issuecomment-979851222) for getting the `uid` and `authToken` for the `etesync` calendar.
118
114
 
115
+ #### Example configuration for etebase_backend (etesync 2.0)
116
+
117
+ This configuration assumes that all the credentials are stored in a plain text (`json`) file. In practice, you would use a more secure storage (perhaps, the `Gnome keyring`) or just read it from the terminal.
118
+
119
+ ```
120
+ from icalcli import EtebaseInterface
121
+ import json
122
+
123
+ conf_file = '/path/to/json-file'
124
+ with open(conf_file, 'r') as fp:
125
+ c = json.load(fp)
126
+
127
+ backend_interface = EtebaseInterface(c['user'], c['server_url'], c['password'],
128
+ c['calendar_uid'], silent=False)
129
+ ```
130
+
131
+ The `calendar_uid` can be obtained using the following code. This code assumes that the `dict c` has been populated with the credentials from the `json` file as above.
132
+
133
+ ```
134
+ from etebase import Client, Account, FetchOptions
135
+
136
+ client = Client(c['user'], c['server_url'])
137
+ etebase = Account.login(client, c['user'], c['password'])
138
+ col_mgr = etebase.get_collection_manager()
139
+ print({col.uid: col.meta
140
+ for col in col_mgr.list("etebase.vevent").data})
141
+ ```
142
+
119
143
  ## Recurring events and default search period
120
144
 
121
145
  `icalcli` understands the `RRULE`, `RDATE`, `EXRULE`, `EXDATE` elements of the `icalendar` specification. These elements can be added while creating or editing events using `--rrule`, `--rdate`, `--exrule` and `--exdate` options.
@@ -4,7 +4,9 @@ __author__ = 'Jayanth Varma (modified gcalcli by Eric Davis et al.)'
4
4
  from icalcli.icalcli import IcalendarInterface # noqa F401
5
5
  try:
6
6
  from icalcli.etesync_backend.etesync_crud import EtesyncCRUD # noqa F401
7
- from icalcli.etesync_backend.etesync_interface import EtesyncInterface # noqa F401
7
+ from icalcli.etesync_backend.etesync_interface import EtesyncInterface # noqa F
8
+ from icalcli.etesync_backend.etebase_crud import EtebaseCRUD # noqa F401
9
+ from icalcli.etesync_backend.etebase_interface import EtebaseInterface # noqa F401
8
10
  except ImportError:
9
11
  pass
10
12
 
@@ -0,0 +1,137 @@
1
+ #!/usr/bin/env python
2
+
3
+ # this is part of the etesync 2.0 backend
4
+ # for etesync 1.0 backend see etesync_crud.py
5
+
6
+ from etebase import Client, Account, FetchOptions
7
+ from time import sleep, time
8
+
9
+ # The EtesyncCRUD class exposes methods for each of the CRUD operations
10
+ # (Create, Retrieve, Update and Delete) and for sync with the server.
11
+ # It handles only one calendar
12
+
13
+ # The class is initialized with user details, authToken and
14
+ # EITHER the encryption password OR the cipher key.
15
+
16
+ # Intended usage is that a calling program (a CLI) obtains user credentials
17
+ # from terminal input or some secure storage (like a key ring)
18
+ # and then creates an instance of EtesyncCRUD as follows:
19
+
20
+ # crud = EtebaseCRUD(user, server_url, password, calendar_uid)
21
+
22
+ # The CLI program can then perform CRUD operations by calling
23
+ # crud.create_event, crud.retrieve_event,
24
+ # crud.update_event and crud.delete_event
25
+
26
+ # The CLI must explicitly call crud.sync when needed. For example:
27
+ # (a) if the server has been updated from another device
28
+ # (b) after any CRUD operation other than Retrieve
29
+
30
+ # No exception handling is done. That is left to the CLI.
31
+
32
+
33
+ class EtebaseCRUD:
34
+ def __init__(self, user, server_url, password, calendar_uid, silent=True):
35
+ """Initialize
36
+
37
+ Parameters
38
+ ----------
39
+ user : etebase username
40
+ password : etebase password
41
+ server_url : url of etebase server
42
+ calendar_uid : uid of calendar
43
+ """
44
+ client = Client(user, server_url)
45
+ etebase = Account.login(client, user, password)
46
+ col_mgr = etebase.get_collection_manager()
47
+ collection = col_mgr.fetch(calendar_uid)
48
+ self.item_mgr = col_mgr.get_item_manager(collection)
49
+ self.sync(silent)
50
+
51
+ def create_event(self, event, uid):
52
+ """Create event
53
+
54
+ Parameters
55
+ ----------
56
+ event : iCalendar file as bytes
57
+ (calendar containing one event to be added)
58
+ """
59
+ item = self.item_mgr.create(
60
+ {
61
+ "name": uid,
62
+ "mtime": int(round(time() * 1000))
63
+ },
64
+ event
65
+ )
66
+ self.item_mgr.batch([item])
67
+
68
+ def update_event(self, event, uid):
69
+ """Edit event
70
+
71
+ Parameters
72
+ ----------
73
+ event : iCalendar file as bytes
74
+ (calendar containing one event to be updated)
75
+ uid : uid of event to be updated
76
+ """
77
+ item = self.item_mgr.fetch(uid)
78
+ item.content = event
79
+ self.item_mgr.batch([item])
80
+
81
+ def retrieve_event(self, uid):
82
+ r"""Retrieve event by uid
83
+
84
+ Parameters
85
+ ----------
86
+ uid : uid of event to be retrieved
87
+
88
+ Returns
89
+ -------
90
+ iCalendar file (as a string)
91
+ """
92
+ return self.item_mgr.fetch(uid).content.decode()
93
+
94
+ def all_events(self):
95
+ """Retrieve all events in calendar
96
+
97
+ Returns
98
+ -------
99
+ List of iCalendar files (as strings)
100
+ """
101
+ return [e.content.decode() for e in self.items.data if not e.deleted]
102
+
103
+ def delete_event(self, uid):
104
+ """Delete event and sync calendar
105
+
106
+ Parameters
107
+ ----------
108
+ uid : uid of event to be deleted
109
+ """
110
+ item = self.item_mgr.fetch(uid)
111
+ item.delete()
112
+ self.item_mgr.batch([item])
113
+
114
+ def sync(self, silent=False):
115
+ """Initialize
116
+
117
+ Parameters
118
+ ----------
119
+ silent : boolean whether to report sync attempt and success
120
+ """
121
+ silent or print("Syncing with server. Please wait")
122
+ msg = "etebase fetch attempt {:} failed. Will retry after {:} seconds"
123
+ delay = 5
124
+ synced = False
125
+ for i in range(5):
126
+ try:
127
+ self.items = self.item_mgr.list(FetchOptions().limit(10**6))
128
+ synced = True
129
+ break
130
+ except Exception:
131
+ silent or print(msg.format(i+1, delay))
132
+ sleep(delay)
133
+ if synced:
134
+ silent or print("Syncing completed.")
135
+ self.all_events()
136
+ else:
137
+ print("Syncing with server failed after 5 attempts")
@@ -0,0 +1,94 @@
1
+ #!/usr/bin/env python
2
+
3
+ # this is part of the etesync 2.0 backend
4
+ # for etesync 1.0 backend see etesync_interface.py
5
+
6
+ from icalcli.etesync_backend.etebase_crud import EtebaseCRUD
7
+ from icalendar import Calendar
8
+
9
+
10
+ # The EtebaseInterface class is basically a wrapper around the
11
+ # EtebaseCRUD class from which it is derived
12
+ # The CRUD operations (Create, Retrieve, Update and Delete)
13
+ # work with icalendar events (VEVENT). While calling EtebaseCRUD methods,
14
+ # both inputs and return values are converted to/from
15
+ # ics calendar bytes/strings
16
+
17
+ # The class is initialized with user details and credentials.
18
+
19
+ # Intended usage is that a calling program obtains user credentials
20
+ # from terminal input or some secure storage (like a key ring)
21
+ # and then creates an instance of EtebaseCRUD as follows:
22
+
23
+ # etes = EtebaseInterface(user, server_url, password, calendar_uid)
24
+
25
+ # The calling program can then perform CRUD operations by calling
26
+ # etes.create_event, etes.retrieve_event,
27
+ # etes.update_event and etes.delete_event
28
+
29
+ # The calling program must explicitly call etes.sync when needed. For example:
30
+ # (a) if the server has been updated from another device
31
+ # (b) after any CRUD operation other than Retrieve
32
+
33
+ # No exception handling is done. That is left to the calling program.
34
+
35
+
36
+ class EtebaseInterface (EtebaseCRUD):
37
+ def __init__(self, user, server_url, password, calendar_uid, silent=True):
38
+ r"""Initialize EtebaseInterface
39
+
40
+ Parameters
41
+ ----------
42
+ user : etebase username
43
+ password : etebase password
44
+ server_url : url of etebase server
45
+ calendar_uid : uid of calendar
46
+ """
47
+ super(EtebaseInterface, self).__init__(
48
+ user, server_url, password, calendar_uid, silent)
49
+ self.all_events()
50
+
51
+ def all_events(self):
52
+ self.events = [Calendar.from_ical(ev).walk('VEVENT')[0]
53
+ for ev in EtebaseCRUD.all_events(self)]
54
+
55
+ def create_event(self, event, vtimezone=None):
56
+ r"""Create event
57
+
58
+ Parameters
59
+ ----------
60
+ event : event to be added (iCalendar object)
61
+ """
62
+ ics = self.event_to_ics(event, vtimezone)
63
+ EtebaseCRUD.create_event(self, ics)
64
+
65
+ def update_event(self, event, vtimezone=None):
66
+ r"""Update event
67
+
68
+ Parameters
69
+ ----------
70
+ event : event to be added (iCalendar object)
71
+ """
72
+ uid = event.decoded('uid').decode()
73
+ ics = self.event_to_ics(event, vtimezone)
74
+ EtebaseCRUD.update_event(self, ics, uid)
75
+
76
+ def event_to_ics(self, event, vtimezone=None):
77
+ r"""Make calendar byte array (ics) from event
78
+
79
+ Parameters
80
+ ----------
81
+ event : event to be added (iCalendar object)
82
+ """
83
+ cal = Calendar()
84
+ cal.add_component(event)
85
+ if vtimezone:
86
+ cal.add_component(vtimezone)
87
+ ics = cal.to_ical()
88
+ return ics
89
+
90
+ def sync(self, vtimezone=None):
91
+ r"""Sync with server and rebuild vevent list
92
+ """
93
+ EtebaseCRUD.sync(self)
94
+ self.all_events()
@@ -1,5 +1,8 @@
1
1
  #!/usr/bin/env python
2
2
 
3
+ # this is part of the etesync 1.0 backend
4
+ # for etesync 2.0 backend see etebase_crud.py
5
+
3
6
  import etesync as api
4
7
  from time import sleep
5
8
 
@@ -1,3 +1,8 @@
1
+ #!/usr/bin/env python
2
+
3
+ # this is part of the etesync 1.0 backend
4
+ # for etesync 2.0 backend see etebase_interface.py
5
+
1
6
  from icalcli.etesync_backend.etesync_crud import EtesyncCRUD
2
7
  from icalendar import Calendar
3
8
 
@@ -61,9 +61,9 @@ class ICSInterface:
61
61
  return
62
62
  if self.backup:
63
63
  with NamedTemporaryFile(mode='w',
64
- suffix=self.filepath.suffix,
65
- prefix=self.filepath.name,
66
- dir=self.filepath.parent,
64
+ suffix=self.filepaths[0].suffix,
65
+ prefix=self.filepaths[0].name,
66
+ dir=self.filepaths[0].parent,
67
67
  delete=False) as fp:
68
68
  fp.write(self.ics)
69
69
  cal = Calendar()
@@ -72,6 +72,6 @@ class ICSInterface:
72
72
  if vtimezone:
73
73
  cal.add_component(vtimezone)
74
74
  self.ics = cal.to_ical().decode()
75
- with open(self.filepath, 'w') as fp:
75
+ with open(self.filepaths[0], 'w') as fp:
76
76
  fp.write(self.ics)
77
77
  self.all_events()
@@ -385,13 +385,13 @@ class IcalendarInterface:
385
385
  decode().strip())
386
386
  if self.graphical_outputs.get('uid'):
387
387
  summary += " <%s>" % (event.Decoded('uid').decode().strip())
388
- # if (
389
- # self.graphical_outputs.get('description')
390
- # and 'description' in event
391
- # and event.Decoded('description').decode().strip()
392
- # and self.outputs.get('description')
393
- # ):
394
- # summary += event.Decoded('description'). decode().strip()
388
+ if (
389
+ self.graphical_outputs.get('description')
390
+ and 'description' in event
391
+ and event.Decoded('description').decode().strip()
392
+ and self.outputs.get('description')
393
+ ):
394
+ summary += event.Decoded('description'). decode().strip()
395
395
  return summary
396
396
 
397
397
  def get_week_events(self, start_dt, end_dt, event_list):
@@ -551,10 +551,11 @@ class IcalendarInterface:
551
551
  -------
552
552
  int: where to cut the word
553
553
  """
554
- print_len = 0
554
+ # print_len = 0
555
555
 
556
556
  words = _u(string).split()
557
557
  for i, word in enumerate(words):
558
+ print_len = self.printed_len(' '.join(words[:i]))
558
559
  word_len = self.printed_len(word)
559
560
  if (
560
561
  (cur_print_len + word_len + print_len
@@ -566,7 +567,7 @@ class IcalendarInterface:
566
567
  if cut_idx == 0:
567
568
  return self.word_cut(word)
568
569
  return (print_len, cut_idx)
569
- print_len += word_len + i # +i for the space between words
570
+ # print_len += word_len + i # +i for the space between words
570
571
  return (print_len, len(' '.join(words[:i])))
571
572
 
572
573
  def get_cut_index(self, event_string):
@@ -741,7 +742,6 @@ class IcalendarInterface:
741
742
  curr_event.title)
742
743
  padding = ' ' * (self.options['cal_width']
743
744
  - print_len)
744
-
745
745
  self.printer.msg(
746
746
  curr_event.title[:cut_idx] + padding,
747
747
  curr_event.color)
@@ -1,3 +1,25 @@
1
+ Metadata-Version: 2.1
2
+ Name: icalcli
3
+ Version: 1.1
4
+ Summary: Icalendar Calendar Command Line Interface
5
+ Home-page: https://github.com/jrvarma/icalcli
6
+ Maintainer: Jayanth R. Varma
7
+ Maintainer-email: jrvarma@gmail.com
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Environment :: Console
10
+ Classifier: Intended Audience :: End Users/Desktop
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Requires-Python: >=3.6
14
+ Description-Content-Type: text/markdown
15
+ License-File: LICENSE
16
+ Requires-Dist: python-dateutil
17
+ Requires-Dist: parsedatetime
18
+ Requires-Dist: icalendar
19
+ Requires-Dist: recurring_ical_events
20
+ Provides-Extra: parsedatetime
21
+ Requires-Dist: parsedatetime; extra == "parsedatetime"
22
+
1
23
  # icalcli
2
24
 
3
25
  ### An iCalendar Command Line Interface
@@ -6,7 +28,7 @@
6
28
 
7
29
  Unlike [gcalcli](https://github.com/insanum/gcalcli) which is tied to Google Calendar, `icalcli` is agnostic to (abstracts away from) the actual backend calendar service. It relies on a backend interface which interacts with the backend calendar to perform all the CRUD (Create, Retrieve, Update and Delete) operations on the actual calendar. The package includes two backends:
8
30
 
9
- * The `etesync_backend` subpackage provides a backend interface to the [EteSync](https://www.etesync.com/) calendar. In fact, `icalcli` was created primarily to provide a command line interface to my self hosted `EteSync` calendar.
31
+ * The `etesync_backend` subpackage provides a backend interface to the [EteSync](https://www.etesync.com/) calendar (versions 1.0 and 2.0). In fact, `icalcli` was created primarily to provide a command line interface to my self hosted `EteSync` calendar.
10
32
 
11
33
  * The `file_backend` subpackage provides a backend interface to a calendar contained in a local `ics` file. This is useful as a viewer/editor of `ics` files. It is also useful to try out `icalci` without having any other backend configured.
12
34
 
@@ -33,6 +55,12 @@ The two included backends would also be useful to those who wish to write their
33
55
  pip install icalcli
34
56
  ```
35
57
 
58
+ or via `pipx`:
59
+
60
+ ```sh
61
+ pipx install icalcli
62
+ ```
63
+
36
64
  ### Install from source
37
65
 
38
66
  ```sh
@@ -40,6 +68,13 @@ git clone https://github.com/jrvarma/icalcli.git
40
68
  cd icalcli
41
69
  python setup.py install
42
70
  ```
71
+
72
+ or via `pipx`:
73
+
74
+ ```sh
75
+ pipx install . --editable
76
+ ```
77
+
43
78
  ## Usage
44
79
 
45
80
  ### Command line arguments
@@ -80,7 +115,7 @@ backend_interface = ICSInterface(["/path/to/ics-file-1", "/path/to/ics-file-2"])
80
115
 
81
116
  ```
82
117
 
83
- #### Example configuration for etesync_backend
118
+ #### Example configuration for etesync_backend (etesync 1.0)
84
119
 
85
120
  This configuration assumes that all the credentials are stored in a plain text (`json`) file. In practice, you would use a more secure storage (perhaps, the `Gnome keyring`) or just read it from the terminal.
86
121
 
@@ -99,6 +134,34 @@ backend_interface = EtesyncInterface(
99
134
  ```
100
135
  See the [Example code](https://github.com/jrvarma/icalcli/issues/1#issuecomment-979851222) for getting the `uid` and `authToken` for the `etesync` calendar.
101
136
 
137
+ #### Example configuration for etebase_backend (etesync 2.0)
138
+
139
+ This configuration assumes that all the credentials are stored in a plain text (`json`) file. In practice, you would use a more secure storage (perhaps, the `Gnome keyring`) or just read it from the terminal.
140
+
141
+ ```
142
+ from icalcli import EtebaseInterface
143
+ import json
144
+
145
+ conf_file = '/path/to/json-file'
146
+ with open(conf_file, 'r') as fp:
147
+ c = json.load(fp)
148
+
149
+ backend_interface = EtebaseInterface(c['user'], c['server_url'], c['password'],
150
+ c['calendar_uid'], silent=False)
151
+ ```
152
+
153
+ The `calendar_uid` can be obtained using the following code. This code assumes that the `dict c` has been populated with the credentials from the `json` file as above.
154
+
155
+ ```
156
+ from etebase import Client, Account, FetchOptions
157
+
158
+ client = Client(c['user'], c['server_url'])
159
+ etebase = Account.login(client, c['user'], c['password'])
160
+ col_mgr = etebase.get_collection_manager()
161
+ print({col.uid: col.meta
162
+ for col in col_mgr.list("etebase.vevent").data})
163
+ ```
164
+
102
165
  ## Recurring events and default search period
103
166
 
104
167
  `icalcli` understands the `RRULE`, `RDATE`, `EXRULE`, `EXDATE` elements of the `icalendar` specification. These elements can be added while creating or editing events using `--rrule`, `--rdate`, `--exrule` and `--exdate` options.
@@ -1,9 +1,6 @@
1
- CHANGELOG.md
2
1
  LICENSE
3
2
  README.md
4
- exclude
5
3
  setup.py
6
- update-github.md
7
4
  icalcli/__init__.py
8
5
  icalcli/argparsers.py
9
6
  icalcli/icalcli.py
@@ -16,6 +13,8 @@ icalcli.egg-info/entry_points.txt
16
13
  icalcli.egg-info/requires.txt
17
14
  icalcli.egg-info/top_level.txt
18
15
  icalcli/etesync_backend/__init__.py
16
+ icalcli/etesync_backend/etebase_crud.py
17
+ icalcli/etesync_backend/etebase_interface.py
19
18
  icalcli/etesync_backend/etesync_crud.py
20
19
  icalcli/etesync_backend/etesync_interface.py
21
20
  icalcli/file_backend/__init__.py
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
5
5
  long_description = fh.read()
6
6
 
7
7
  setup(name='icalcli',
8
- version='1.0.5',
8
+ version='1.1',
9
9
  maintainer='Jayanth R. Varma',
10
10
  maintainer_email='jrvarma@gmail.com',
11
11
  description='Icalendar Calendar Command Line Interface',
@@ -1,45 +0,0 @@
1
- # 1.0.5 released 2024-04-17
2
-
3
- * Added `cal5w` command to provide current week, two past weeks and two future weeks in a calendar format.
4
- * Introduced option to get more event details (end time, alarm, location, free/busy) in week and calendar views.
5
- * Extended the file backend to allow multiple `ics` files in read only mode.
6
-
7
- # 1.0.4 released 2022-10-11
8
- Bug fixes
9
-
10
- # 1.0.3 released 2022-09-19
11
- Bug fixes
12
-
13
- # 1.0.2 released 2022-08-17
14
- Bug fixes
15
-
16
- # 1.0.1 released 2022-08-16
17
- Bug fixes
18
-
19
- # 1.0.0 released 2022-08-16
20
-
21
- ## Added
22
-
23
- * Added support for recurring events using [python-recurring-ical-events ](https://github.com/niccokunzmann/python-recurring-ical-events).
24
- * It is also possible to create and edit recurring events The recurrence rule has to be given as a string using the `--rrule` option to the `add` and `edit` commands (for example `--rrule FREQ=DAILY;COUNT=5`). Editing/deleting modifies/deletes all occurrences of the event. To delete a single occurrence, use `--exdate`.
25
- * Added support for creating/editing events using raw ICS text. This is mainly for properties (like `attendee` and `comment`) that are not available as command line options.
26
- * If duplicate UIDs are found, they are de-duplicated and the calendar is opened in read only mode. Editing a file with multiple UIDs is dangerous.
27
-
28
- ## Changed
29
-
30
- * Searching for events without any start or end parameters now returns event occurrences only within the last 5 years and next 5 years (this number can be changed with the option `--default_past_years` and `--default_future_years`). More events can be obtained using explicit start and end parameters. For example, `s home '-10 y' 15y` will go back 10 years and forward 15 years. This change was necessitated because a single recurring event (without any `COUNT` or `UNTIL` restrictions) can generate an infinite number of occurrences.
31
- * The `-u` or `--uid` option has been removed and replaced by a more general `-p` or `--property` option that allows any property of the event to be searched. For example, `s -p rrule DAILY` will display all events with a recurrence rule that has a daily frequency.
32
- * Many Bug fixes.
33
- * Several method names were changed (the leading underscore was dropped from all method names), but these were intended to be used only internally.
34
-
35
- # 0.9.9 released 2022-07-12
36
-
37
- ## Added
38
-
39
- * Check for errors while parsing `iCalendar` events
40
- * Added option to provide stack trace for errors. By default, most errors are caught using try blocks and only a cryptic summary is provided. With this option, the stack trace is printed, but the program continues to run.
41
-
42
- ## Changed
43
-
44
- * A few bug fixes
45
-
icalcli-1.0.5/exclude DELETED
@@ -1,7 +0,0 @@
1
- **build**
2
- **dist**
3
- **file_backend_n_screenshots**
4
- **egg-info**
5
- **__pycache__**
6
- exclude
7
- update-github.md
@@ -1,33 +0,0 @@
1
- # After updating local file in /0/bp/
2
-
3
- * Update local github folder with remote by Pull from origin/master
4
- * `rsync -avc --dry-run --exclude-from ~/0/bp/icalcli/exclude \
5
- /home/jrvarma/0/bp/icalcli/ /home/jrvarma/0/src/github/icalcli/`
6
- * `rsync -avc --exclude-from ~/0/bp/icalcli/exclude \
7
- /home/jrvarma/0/bp/icalcli/ /home/jrvarma/0/src/github/icalcli/`
8
- * Commit changes in local github folder
9
- * Push to remote origin/master
10
-
11
- # After updating repo
12
-
13
- * `rsync -avc --dry-run --exclude '.git/' --exclude screenshots\
14
- ~/0/src/github/icalcli/ ~/0/bp/icalcli/ `
15
- * `rsync -avc --exclude '.git/' \
16
- ~/0/src/github/icalcli/ ~/0/bp/icalcli/ `
17
-
18
- ## Update PyPi
19
-
20
- * Bump version number (Edit `setup.py`)
21
-
22
- ```
23
- cd ~/0/bp/icalcli
24
- rm /0/bp/icalcli/dist/*
25
- python3 setup.py sdist bdist_wheel
26
- python3 -m twine upload dist/*
27
- ```
28
-
29
- ## Install new version from PyPi
30
-
31
- ```
32
- pip install --upgrade icalcli
33
- ```
File without changes
File without changes
File without changes
File without changes
File without changes