pathpilot 0.2.2__tar.gz → 0.3.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.
@@ -1,8 +1,7 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: pathpilot
3
- Version: 0.2.2
3
+ Version: 0.3.1
4
4
  Summary: Library that facilitates file and folder manipulation in Python.
5
- Home-page: https://github.com/zteinck/pathpilot
6
5
  License: MIT
7
6
  Author: Zachary Einck
8
7
  Author-email: zacharyeinck@gmail.com
@@ -14,12 +13,14 @@ Classifier: Programming Language :: Python :: 3.9
14
13
  Classifier: Programming Language :: Python :: 3.10
15
14
  Classifier: Programming Language :: Python :: 3.11
16
15
  Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
17
  Requires-Dist: XlsxWriter
18
18
  Requires-Dist: cachegrab (>=0.2.2)
19
- Requires-Dist: clockwork (>=0.2.2)
19
+ Requires-Dist: clockwork (>=0.3.4)
20
20
  Requires-Dist: numpy
21
- Requires-Dist: oddments (>=0.2.0)
21
+ Requires-Dist: oddments (>=0.3.1)
22
22
  Requires-Dist: pandas
23
+ Project-URL: Homepage, https://github.com/zteinck/pathpilot
23
24
  Project-URL: Repository, https://github.com/zteinck/pathpilot
24
25
  Description-Content-Type: text/markdown
25
26
 
@@ -42,7 +43,7 @@ pip install pathpilot
42
43
 
43
44
 
44
45
  ## Main Features
45
- - `File` ➔ Function that assigns new file instances to the correct child class. Many file types are supported natively including: *.xlsx*, *.csv*, *.txt*, *.pickle*, etc. The mapping of file extensions to their respective classes is managed using the `extension_mapping` global dictionary. Unmapped extensions are assigned to the `FileBase` class.
46
+ - `file_factory` ➔ Function that assigns new file instances to the correct child class. Many file types are supported natively including: *.xlsx*, *.csv*, *.txt*, *.pickle*, etc. The mapping of file extensions to their respective classes is managed using the `extension_mapping` global dictionary. Unmapped extensions are assigned to the `FileBase` class.
46
47
  - `Folder` ➔ Class for interacting with folders. It is important to be mindful of the `read_only` parameter which, if set to `True`, allows folders to be created or deleted programically.
47
48
 
48
49
 
@@ -51,7 +52,7 @@ Please note the examples below represent a small fraction of the functionality o
51
52
 
52
53
  ### Imports
53
54
  ```python
54
- from pathpilot import Folder, File
55
+ from pathpilot import Folder, file_factory
55
56
  ```
56
57
 
57
58
  ### Folders
@@ -79,10 +80,10 @@ new_years_file = january_folder.join('Happy New Year.txt')
79
80
  ```
80
81
 
81
82
  ### Files
82
- First, we create an instance of the `ExcelFile` class using the `File` function. This occurs automatically by virtue of the `.xlsx` file extension.
83
+ First, we create an instance of the `ExcelFile` class using the `file_factory` function. This occurs automatically by virtue of the `.xlsx` file extension.
83
84
  ```python
84
85
  # create ExcelFile instance
85
- file = File(r'C:\Users\MyID\Documents\MyFolder\MyFile.xlsx')
86
+ file = file_factory(r'C:\Users\MyID\Documents\MyFolder\MyFile.xlsx')
86
87
  ```
87
88
 
88
89
  Next, let's check if the file exists. If not, let's save a `pandas` `DataFrame` as an Excel file.
@@ -100,7 +101,7 @@ Creating MyFile.xlsx
100
101
 
101
102
  Now let's read the file we created as a `DataFrame`.
102
103
  ```python
103
- # read the file we created as a pd.DataFrame
104
+ # read the file we created as a pd.DataFrame
104
105
  df = file.read()
105
106
  ```
106
107
 
@@ -17,7 +17,7 @@ pip install pathpilot
17
17
 
18
18
 
19
19
  ## Main Features
20
- - `File` ➔ Function that assigns new file instances to the correct child class. Many file types are supported natively including: *.xlsx*, *.csv*, *.txt*, *.pickle*, etc. The mapping of file extensions to their respective classes is managed using the `extension_mapping` global dictionary. Unmapped extensions are assigned to the `FileBase` class.
20
+ - `file_factory` ➔ Function that assigns new file instances to the correct child class. Many file types are supported natively including: *.xlsx*, *.csv*, *.txt*, *.pickle*, etc. The mapping of file extensions to their respective classes is managed using the `extension_mapping` global dictionary. Unmapped extensions are assigned to the `FileBase` class.
21
21
  - `Folder` ➔ Class for interacting with folders. It is important to be mindful of the `read_only` parameter which, if set to `True`, allows folders to be created or deleted programically.
22
22
 
23
23
 
@@ -26,7 +26,7 @@ Please note the examples below represent a small fraction of the functionality o
26
26
 
27
27
  ### Imports
28
28
  ```python
29
- from pathpilot import Folder, File
29
+ from pathpilot import Folder, file_factory
30
30
  ```
31
31
 
32
32
  ### Folders
@@ -54,10 +54,10 @@ new_years_file = january_folder.join('Happy New Year.txt')
54
54
  ```
55
55
 
56
56
  ### Files
57
- First, we create an instance of the `ExcelFile` class using the `File` function. This occurs automatically by virtue of the `.xlsx` file extension.
57
+ First, we create an instance of the `ExcelFile` class using the `file_factory` function. This occurs automatically by virtue of the `.xlsx` file extension.
58
58
  ```python
59
59
  # create ExcelFile instance
60
- file = File(r'C:\Users\MyID\Documents\MyFolder\MyFile.xlsx')
60
+ file = file_factory(r'C:\Users\MyID\Documents\MyFolder\MyFile.xlsx')
61
61
  ```
62
62
 
63
63
  Next, let's check if the file exists. If not, let's save a `pandas` `DataFrame` as an Excel file.
@@ -75,7 +75,7 @@ Creating MyFile.xlsx
75
75
 
76
76
  Now let's read the file we created as a `DataFrame`.
77
77
  ```python
78
- # read the file we created as a pd.DataFrame
78
+ # read the file we created as a pd.DataFrame
79
79
  df = file.read()
80
80
  ```
81
81
 
@@ -3,5 +3,5 @@ from .decorators import *
3
3
  from .exceptions import *
4
4
  from .utils import *
5
5
 
6
- __version__ = '0.2.2'
6
+ __version__ = '0.3.1'
7
7
  __author__ = 'Zachary Einck <zacharyeinck@gmail.com>'
@@ -54,8 +54,6 @@ class ExcelFile(FileBase):
54
54
  keeps track of the current tab number
55
55
  verbose : bool
56
56
  if True, information is printed when a worksheet is created or written to.
57
- troubleshoot : bool
58
- if True, additional information is printed for troubleshooting purposes.
59
57
 
60
58
  Note:
61
59
  --------------------
@@ -73,16 +71,14 @@ class ExcelFile(FileBase):
73
71
  f,
74
72
  number_tabs=False,
75
73
  verbose=True,
76
- troubleshoot=False,
77
74
  **kwargs
78
75
  ):
79
76
  super().__init__(f, **kwargs)
80
77
  self.format_cache = dict()
81
78
  self.sheet_cache = dict()
82
79
  self.number_tabs = number_tabs
83
- self.page = 0
84
80
  self.verbose = verbose
85
- self.troubleshoot = troubleshoot
81
+ self.page = 0
86
82
 
87
83
 
88
84
  #╭-------------------------------------------------------------------------╮
@@ -204,7 +200,8 @@ class ExcelFile(FileBase):
204
200
  @property
205
201
  def active_sheet(self):
206
202
  ''' current active worksheet '''
207
- # used __dict__ because hasattr calls __getattr__ when attr not found in __dict__
203
+ # used __dict__ because hasattr calls __getattr__
204
+ # when attr not found in __dict__
208
205
  if '_active_sheet' not in self.__dict__:
209
206
  self.create_worksheet('Sheet1')
210
207
  return self._active_sheet
@@ -332,10 +329,6 @@ class ExcelFile(FileBase):
332
329
  out : *
333
330
  xlsxwriter.worksheet.Worksheet attribute
334
331
  '''
335
-
336
- if self.troubleshoot:
337
- print(f"self.__getattr__(name='{name}')")
338
-
339
332
  return getattr(self.active_sheet, name)
340
333
 
341
334
 
@@ -586,10 +579,15 @@ class ExcelFile(FileBase):
586
579
 
587
580
  if self.verbose:
588
581
  size_label = get_size_label(sys.getsizeof(data))
589
- print(f"\twriting {size_label} to '{self.active_sheet.name}' tab", end='... ')
582
+ print(
583
+ f'\twriting {size_label} to '
584
+ f'{self.active_sheet.name!r} tab',
585
+ end='... '
586
+ )
590
587
 
591
588
  if not data:
592
- if self.verbose: print('SKIPPED')
589
+ if self.verbose:
590
+ print('SKIPPED')
593
591
  return
594
592
 
595
593
  start_col, start_row = self.parse_start_cell(start_cell)
@@ -648,10 +646,10 @@ class ExcelFile(FileBase):
648
646
  '''
649
647
  Description
650
648
  ------------
651
- Writes a DataFrame to an Excel worksheet. This is an alternative to df.to_excel()
652
- that addresses some of its limitations such as not being able format cells that
653
- already have a format including the index, headers, and cells that contain dates
654
- or datetimes.
649
+ Writes a DataFrame to an Excel worksheet. This is an alternative to
650
+ df.to_excel() that addresses some of its limitations such as not being
651
+ able format cells that already have a format including the index,
652
+ headers, and cells that contain dates or datetimes.
655
653
 
656
654
  Parameters
657
655
  ------------
@@ -748,10 +746,16 @@ class ExcelFile(FileBase):
748
746
  # Check if empty
749
747
  if df.empty:
750
748
  if raise_on_empty:
751
- raise ValueError("'df' argument cannot be empty.")
749
+ raise ValueError(
750
+ "'df' argument cannot be empty."
751
+ )
752
752
  if len(df.columns) == 0:
753
- raise ValueError("'df' argument must have an index or columns")
754
- total_row, total_column = False, False
753
+ raise ValueError(
754
+ "'df' argument must have "
755
+ "an index or columns."
756
+ )
757
+ total_row = False
758
+ total_column = False
755
759
 
756
760
  # Check for duplicate column names
757
761
  odd.verify_no_duplicates(df=df, attr='columns')
@@ -761,7 +765,8 @@ class ExcelFile(FileBase):
761
765
  total_column_name = 'Total'
762
766
  if total_column_name in df.columns:
763
767
  raise ValueError(
764
- f"'df' already has a column named '{total_column_name}'"
768
+ "'df' already has a column "
769
+ f"named {total_column_name!r}"
765
770
  )
766
771
  df[total_column_name] = df.sum(axis=1, numeric_only=True)
767
772
 
@@ -776,13 +781,14 @@ class ExcelFile(FileBase):
776
781
  numeric_columns -= percent_columns
777
782
 
778
783
  datelike_columns = set(
779
- df.select_dtypes(include=[np.datetime64]).columns.tolist()
784
+ df.select_dtypes(include=[np.datetime64])\
785
+ .columns.tolist()
780
786
  )
781
787
 
782
788
  for k in df.columns:
783
- if isinstance(k, str) and \
784
- odd.column_name_is_datelike(k) and \
785
- str(df[k].dtype) != 'timedelta64[ns]':
789
+ if isinstance(k, str) \
790
+ and odd.column_name_is_datelike(k) \
791
+ and not np.issubdtype(df[k].dtype, np.timedelta64):
786
792
  datelike_columns.add(k)
787
793
 
788
794
  # Parse start cell
@@ -799,6 +805,7 @@ class ExcelFile(FileBase):
799
805
 
800
806
  # Force data_format to comply with the standard {column name : format}
801
807
  if isinstance(data_format, dict):
808
+ # check if diciontary keys are index/column names
802
809
  if not all(k in df.columns for k in data_format):
803
810
  if any(isinstance(v, (list, tuple, dict))
804
811
  for v in data_format.values()):
@@ -807,14 +814,15 @@ class ExcelFile(FileBase):
807
814
 
808
815
  # Auto-detects the best format for each DataFrame column
809
816
  if data_format == 'auto':
810
- data_format = dict()
811
817
 
812
818
  # cascade auto formatting
813
819
  if total_row_format is None:
814
- total_row_format = 'auto'
820
+ total_row_format = data_format[:]
815
821
 
816
822
  if total_column_format is None:
817
- total_column_format = 'auto'
823
+ total_column_format = data_format[:]
824
+
825
+ data_format = {}
818
826
 
819
827
  infer_format = lambda fmt, s: \
820
828
  fmt if s.sum() - s.round().sum() == 0 \
@@ -848,18 +856,33 @@ class ExcelFile(FileBase):
848
856
  datetime_columns = set()
849
857
 
850
858
  for k in list(datelike_columns):
851
- if np.issubdtype(df[k].dtype, np.datetime64): continue
859
+ if np.issubdtype(df[k].dtype, np.datetime64) \
860
+ or df[k].isna().all():
861
+ continue
862
+
852
863
  fmt = date_formats.get(k)
864
+ to_dt = lambda x: pd.to_datetime(x, format=fmt)
865
+
853
866
  try:
854
- df[k] = pd.to_datetime(df[k], format=fmt)
867
+ df[k] = to_dt(df[k])
855
868
  except:
856
- if fmt is None:
857
- datelike_columns.remove(k)
858
- else:
859
- df[k] = df[k].apply(odd.ignore_nan(lambda x: \
860
- datetime.datetime.strptime(x, fmt)
861
- ))
862
- datetime_columns.add(k)
869
+ try:
870
+ # handles mixed dtypes that will convert individually
871
+ df[k] = df[k].apply(odd.ignore_nan(to_dt))
872
+ except:
873
+ types = set(type(x) for x in df[k].dropna())
874
+ if types == {str}:
875
+ if fmt is None:
876
+ datelike_columns.remove(k)
877
+ else:
878
+ df[k] = df[k].apply(odd.ignore_nan(lambda x: \
879
+ datetime.datetime.strptime(x, fmt)
880
+ ))
881
+ datetime_columns.add(k)
882
+ elif all(issubclass(x, datetime.datetime) for x in types):
883
+ datetime_columns.add(k)
884
+ else:
885
+ datelike_columns.remove(k)
863
886
 
864
887
  for k in datelike_columns:
865
888
  data_format[k] = 'datetime'
@@ -867,7 +890,7 @@ class ExcelFile(FileBase):
867
890
  s = df[k].dropna()
868
891
  if s.empty: continue
869
892
  if k in datetime_columns:
870
- if all(x.time() == datetime.time(0, 0) for x in s.values):
893
+ if all(x.time() == datetime.time.min for x in s.values):
871
894
  df[k] = df[k].apply(odd.ignore_nan(lambda x: x.date()))
872
895
  data_format[k] = 'date'
873
896
  else:
@@ -5,7 +5,6 @@ import os
5
5
  import pandas as pd
6
6
  import numpy as np
7
7
  import oddments as odd
8
- import clockwork as cw
9
8
  from cachegrab import sha256
10
9
 
11
10
  from .._folder import Folder
@@ -135,34 +134,6 @@ class FileBase(object):
135
134
  return wrapper
136
135
 
137
136
 
138
- @staticmethod
139
- def add_timestamp(func):
140
- '''
141
- Parameters
142
- ------------
143
- args : tuple
144
- arguments are only passed to the respective clockwork function
145
- kwargs : dict
146
- keyword arguments are passed to the respective clockwork function
147
- with the exception of 'loc' and 'encase':
148
-
149
- loc : str
150
- the location where you want the timestamp.
151
- Supported values are 'prefix' and 'suffix'
152
- encase : bool
153
- if True, the timestamp is encased in paranthesis
154
- '''
155
-
156
- def wrapper(self, *args, **kwargs):
157
- loc = kwargs.pop('loc', 'prefix')
158
- encase = kwargs.pop('encase', False)
159
- timestamp = func(self, *args, **kwargs)
160
- if encase: timestamp = f'({timestamp})'
161
- return getattr(self, loc)(timestamp)
162
-
163
- return wrapper
164
-
165
-
166
137
  @staticmethod
167
138
  def add_affix(func):
168
139
  '''
@@ -195,16 +166,16 @@ class FileBase(object):
195
166
  '''
196
167
  Description
197
168
  ------------
198
- This method ensures that functions returning new instances create objects
199
- of the correct subclass. For instance, if a CSVFile instance is converted
200
- to an Excel file, this method guarantees that the returned instance is
201
- an ExcelFile object. If subclass typing must be preserved regardless of
202
- changes, the subclass can set the factory to None. For example, a
203
- CryptoFile should always create instances of CryptoFile even if the
204
- file extension is changed.
169
+ This method ensures that functions returning new instances create
170
+ objects of the correct subclass. For instance, if a CSVFile instance is
171
+ converted to an Excel file, this method guarantees that the returned
172
+ instance is an ExcelFile object. If subclass typing must be preserved
173
+ regardless of changes, the subclass can set the factory to None. For
174
+ example, a CryptoFile should always create instances of CryptoFile even
175
+ if the file extension is changed.
205
176
 
206
- Note: This must be at the class level since calling self.factory() at
207
- the instance level passes self as the first argument.
177
+ Note: This must be at the class level since calling self.file_factory()
178
+ at the instance level passes self as the first argument.
208
179
 
209
180
  Parameters
210
181
  ------------
@@ -218,7 +189,8 @@ class FileBase(object):
218
189
  file : FileBase subclass instance
219
190
  spawned file instance
220
191
  '''
221
- return (cls if cls.factory is None else cls.factory)(*args, **kwargs)
192
+ ff = cls.file_factory
193
+ return (cls if ff is None else ff)(*args, **kwargs)
222
194
 
223
195
 
224
196
  #╭-------------------------------------------------------------------------╮
@@ -489,7 +461,7 @@ class FileBase(object):
489
461
 
490
462
 
491
463
  def deep_copy(self):
492
- ''' create a copy of the File object '''
464
+ ''' create a copy of the file object '''
493
465
  return self.spawn(self.path)
494
466
 
495
467
 
@@ -500,36 +472,4 @@ class FileBase(object):
500
472
 
501
473
  @Decorators.add_affix
502
474
  def suffix():
503
- ''' add suffix to file name '''
504
-
505
-
506
- # helper functions adding timestamps to files
507
- @Decorators.add_timestamp
508
- def quarter(self, delta=0):
509
- return cw.quarter_end(delta=delta).label
510
-
511
-
512
- def qtr(self, *args, **kwargs):
513
- return self.quarter(*args, **kwargs)
514
-
515
-
516
- @Decorators.add_timestamp
517
- def month(self, delta=0):
518
- return cw.month_end(delta=delta).ymd
519
-
520
-
521
- @Decorators.add_timestamp
522
- def day(self, weekday, delta=0):
523
- return cw.day_of_week(weekday=weekday, delta=delta).ymd
524
-
525
-
526
- @Decorators.add_timestamp
527
- def year(self, delta=0):
528
- return str(cw.year_end(delta=delta).year)
529
-
530
-
531
- @Decorators.add_timestamp
532
- def timestamp(self, normalize=False, week_offset=0, fmt=None):
533
- now = cw.Date(normalize=normalize, week_offset=week_offset)
534
- now = str(now).replace(':','.') if fmt is None else now.str(fmt)
535
- return now
475
+ ''' add suffix to file name '''
@@ -3,11 +3,8 @@ import shutil
3
3
  import os
4
4
  import pandas as pd
5
5
  import oddments as odd
6
- from cachegrab import sha256
7
-
8
6
  import clockwork as cw
9
- from clockwork.utils import \
10
- convert_date_format_to_regex
7
+ from cachegrab import sha256
11
8
 
12
9
  from ..decorators import check_read_only
13
10
  from ..exceptions import ReadOnlyError
@@ -36,7 +33,7 @@ class Folder(object):
36
33
 
37
34
  Class Attributes
38
35
  --------------------
39
- factory : object
36
+ file_factory : object
40
37
  Function or class that determines which subclass is returned when
41
38
  a new file object is initialized.
42
39
  sorter : func
@@ -319,7 +316,7 @@ class Folder(object):
319
316
  raise ValueError(' '.join(message + ['found.']))
320
317
 
321
318
  if date_format is not None and date_pattern is None:
322
- date_pattern = convert_date_format_to_regex(date_format)
319
+ date_pattern = cw.date_format_to_regex(date_format)
323
320
 
324
321
  if date_pattern is not None:
325
322
  date_pattern = format_date_pattern(date_pattern)
@@ -454,7 +451,7 @@ class Folder(object):
454
451
 
455
452
  @classmethod
456
453
  def _spawn_file(cls, *args, **kwargs):
457
- return cls.factory(*args, **kwargs)
454
+ return cls.file_factory(*args, **kwargs)
458
455
 
459
456
 
460
457
  @classmethod
@@ -784,7 +781,7 @@ class Folder(object):
784
781
 
785
782
  Returns
786
783
  ----------
787
- out : Folder | File
784
+ out : object
788
785
  folder or file object
789
786
  '''
790
787
  self.validate_join_args(args)
@@ -841,23 +838,6 @@ class Folder(object):
841
838
  shutil.copytree(self.path, destination.path)
842
839
 
843
840
 
844
- # helper functions adding timestamps to folders
845
- def quarter(self, delta=0, **kwargs):
846
- return self.join(cw.quarter_end(delta=delta).label, **kwargs)
847
-
848
-
849
- def month(self, delta=0, **kwargs):
850
- return self.join(cw.month_end(delta=delta).ymd, **kwargs)
851
-
852
-
853
- def day(self, weekday, delta=0, **kwargs):
854
- return self.join(cw.day_of_week(weekday=weekday, delta=delta).ymd, **kwargs)
855
-
856
-
857
- def year(self, delta=0, **kwargs):
858
- return self.join(str(cw.year_end(delta=delta).year), **kwargs)
859
-
860
-
861
841
  #╭-------------------------------------------------------------------------╮
862
842
  #| Static Methods |
863
843
  #╰-------------------------------------------------------------------------╯
@@ -27,7 +27,7 @@ extension_mapping = {
27
27
  #| Functions |
28
28
  #╰-------------------------------------------------------------------------╯
29
29
 
30
- def File(f, **kwargs):
30
+ def file_factory(f, **kwargs):
31
31
  ''' assigns new file instances to the correct subclass '''
32
32
  extension = trifurcate(f)[-1]
33
33
  out = extension_mapping.get(extension, FileBase)(f, **kwargs)
@@ -44,8 +44,8 @@ def get_data_path():
44
44
 
45
45
 
46
46
  #╭-------------------------------------------------------------------------╮
47
- #| Assign Class Attribute |
47
+ #| Assign Class Attributes |
48
48
  #╰-------------------------------------------------------------------------╯
49
49
 
50
- FileBase.factory = File
51
- Folder.factory = File
50
+ FileBase.file_factory = file_factory
51
+ Folder.file_factory = file_factory
@@ -1,6 +1,6 @@
1
1
  import os
2
2
  import datetime
3
- from clockwork import Date
3
+ import clockwork as cw
4
4
 
5
5
 
6
6
  def split_extension(x):
@@ -53,19 +53,28 @@ def get_cwd():
53
53
  return f
54
54
 
55
55
 
56
- def _timestamp_to_date(func):
56
+ def _to_timestamp(func):
57
57
 
58
58
  def wrapper(path):
59
- return Date(datetime.datetime.fromtimestamp(func(path)))
59
+ letter = func.__name__.split('_')[1][0]
60
+ ts = getattr(os.path, f'get{letter}time')(path)
61
+
62
+ # Conversion to datetime is redundant since cw.Timestamp
63
+ # constructor accepts timestamps, but explicitly using
64
+ # datetime library ensures time zone information is
65
+ # respected in case constructor behavior ever changes.
66
+ dt = datetime.datetime.fromtimestamp(ts)
67
+
68
+ return cw.Timestamp(dt)
60
69
 
61
70
  return wrapper
62
71
 
63
72
 
64
- @_timestamp_to_date
65
- def get_created_date(path):
66
- return os.path.getctime(path)
73
+ @_to_timestamp
74
+ def get_created_date():
75
+ pass
67
76
 
68
77
 
69
- @_timestamp_to_date
70
- def get_modified_date(path):
71
- return os.path.getmtime(path)
78
+ @_to_timestamp
79
+ def get_modified_date():
80
+ pass
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "pathpilot"
3
- version = "0.2.2"
3
+ version = "0.3.1"
4
4
  description = "Library that facilitates file and folder manipulation in Python."
5
5
  authors = ["Zachary Einck <zacharyeinck@gmail.com>"]
6
6
  license = "MIT"
@@ -10,9 +10,9 @@ homepage = "https://github.com/zteinck/pathpilot"
10
10
 
11
11
  [tool.poetry.dependencies]
12
12
  python = "^3.8"
13
- clockwork = ">=0.2.2"
13
+ clockwork = ">=0.3.4"
14
14
  cachegrab = ">=0.2.2"
15
- oddments = ">=0.2.0"
15
+ oddments = ">=0.3.1"
16
16
  pandas = "*"
17
17
  numpy = "*"
18
18
  XlsxWriter = "*"
File without changes