checkoff 0.41.0 → 0.43.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ca8318553efc488d88a70b394e290ec8030f532ac9b3d4fa4fc67eb60849270a
4
- data.tar.gz: cd86cc76ca2f74bed8e35212da234f5cbcad358db6a08d181f702fda149e785a
3
+ metadata.gz: af9b4c58d6440cc99eab9508632a3140d3f1519ad32fdf5f21b65833291999ba
4
+ data.tar.gz: 8d32790e9071087f948f9c1e3a3f3870f2de3dd0a1ab835e2b3727b7725d69e0
5
5
  SHA512:
6
- metadata.gz: ecde71759c34fe1cee589084e7c06577726af223cc207f3cb4236f02d3d4fba75662bf622d69de7cabc7f22acb6f041cd8ddfeb142f60aba07051b35a3ac9e00
7
- data.tar.gz: bb87fb6a83333fc0efffcd4ce5a37da55689bd617642a15dbbb4b4a1c94cb8511aa9a2e9d11e4fc16fc6ec6631d8191976e125156a1241b8f27367fb0afd4d27
6
+ metadata.gz: cf699102f03d8d6169e317f94aa88229537626ea74ec3b17446396e35fcf7e9d758d1b881d3c0d4fade4324a52e4ec64ed60d6540cac736e11440a9b4fbb1ca4
7
+ data.tar.gz: ea3952f4603dcb3344b856df43f11686589f8341763bb360d467bb99c852922b8480c3a41a86829dd25a79d3874561675e4ac4d98e09dddbc059720d86577583
data/Gemfile.lock CHANGED
@@ -12,7 +12,7 @@ GIT
12
12
  PATH
13
13
  remote: .
14
14
  specs:
15
- checkoff (0.41.0)
15
+ checkoff (0.43.0)
16
16
  activesupport
17
17
  asana (> 0.10.0)
18
18
  cache_method
@@ -8,19 +8,27 @@ module Checkoff
8
8
  # Use the provided config from a YAML file, and fall back to env
9
9
  # variable if it's not populated for a key'
10
10
  class EnvFallbackConfigLoader
11
+ # @param config [Hash<Symbol, Object>]
12
+ # @param sym [Symbol]
13
+ # @param yaml_filename [String]
11
14
  def initialize(config, sym, yaml_filename)
12
15
  @config = config
13
16
  @envvar_prefix = sym.upcase
14
17
  @yaml_filename = yaml_filename
15
18
  end
16
19
 
20
+ # @param key [Symbol]
21
+ # @return [Object]
17
22
  def [](key)
18
23
  config_value = @config[key]
19
24
  return config_value unless config_value.nil?
20
25
 
26
+ # @sg-ignore
21
27
  ENV.fetch(envvar_name(key), nil)
22
28
  end
23
29
 
30
+ # @param key [Symbol]
31
+ # @return [Object]
24
32
  def fetch(key)
25
33
  out = self[key]
26
34
  return out unless out.nil?
@@ -31,6 +39,8 @@ module Checkoff
31
39
 
32
40
  private
33
41
 
42
+ # @param key [Symbol]
43
+ # @return [String]
34
44
  def envvar_name(key)
35
45
  "#{@envvar_prefix}__#{key.upcase}"
36
46
  end
@@ -39,7 +49,8 @@ module Checkoff
39
49
  # Load configuration file
40
50
  class ConfigLoader
41
51
  class << self
42
- # @return EnvFallbackConfigLoader
52
+ # @sg-ignore
53
+ # @return [Hash<Symbol, Object>]
43
54
  def load(sym)
44
55
  yaml_result = load_yaml_file(sym)
45
56
  EnvFallbackConfigLoader.new(yaml_result, sym, yaml_filename(sym))
@@ -47,13 +58,18 @@ module Checkoff
47
58
 
48
59
  private
49
60
 
61
+ # @param sym [Symbol]
62
+ # @return [Hash<[String, Symbol], Object>]
50
63
  def load_yaml_file(sym)
51
64
  filename = yaml_filename(sym)
52
65
  return {} unless File.exist?(filename)
53
66
 
67
+ # @sg-ignore
54
68
  YAML.load_file(filename).with_indifferent_access
55
69
  end
56
70
 
71
+ # @param sym [Symbol]
72
+ # @return [String]
57
73
  def yaml_filename(sym)
58
74
  file = "#{sym}.yml"
59
75
  File.expand_path("~/.#{file}")
@@ -3,7 +3,7 @@
3
3
  module Checkoff
4
4
  # Base class to evaluate a task selector function given fully evaluated arguments
5
5
  class FunctionEvaluator
6
- # @param task_selector [Array<(Symbol, Array)>]
6
+ # @param task_selector [Array<(Symbol, Array)>,String]
7
7
  # @param tasks [Checkoff::Tasks]
8
8
  def initialize(task_selector:,
9
9
  tasks:)
@@ -101,7 +101,7 @@ module Checkoff
101
101
  def pull_custom_field_by_name(task, custom_field_name)
102
102
  custom_fields = task.custom_fields
103
103
  if custom_fields.nil?
104
- raise "custom fields not found on task - did you add 'custom_field' in your extra_fields argument?"
104
+ raise "custom fields not found on task - did you add 'custom_fields' in your extra_fields argument?"
105
105
  end
106
106
 
107
107
  # @sg-ignore
@@ -165,6 +165,21 @@ module Checkoff
165
165
  end
166
166
  end
167
167
 
168
+ # :equals? function
169
+ class EqualsPFunctionEvaluator < FunctionEvaluator
170
+ def matches?
171
+ fn?(task_selector, :equals?)
172
+ end
173
+
174
+ # @param _task [Asana::Resources::Task]
175
+ # @param lhs [Object]
176
+ # @param rhs [Object]
177
+ # @return [Boolean]
178
+ def evaluate(_task, lhs, rhs)
179
+ lhs == rhs
180
+ end
181
+ end
182
+
168
183
  # :tag function
169
184
  class TagPFunctionEvaluator < FunctionEvaluator
170
185
  def matches?
@@ -324,6 +339,20 @@ module Checkoff
324
339
  end
325
340
  end
326
341
 
342
+ # String literals
343
+ class StringLiteralEvaluator < FunctionEvaluator
344
+ def matches?
345
+ task_selector.is_a?(String)
346
+ end
347
+
348
+ # @sg-ignore
349
+ # @param _task [Asana::Resources::Task]
350
+ # @return [String]
351
+ def evaluate(_task)
352
+ task_selector
353
+ end
354
+ end
355
+
327
356
  # Evaluator task selectors against a task
328
357
  class TaskSelectorEvaluator
329
358
  # @param task [Asana::Resources::Task]
@@ -337,6 +366,7 @@ module Checkoff
337
366
  FUNCTION_EVALUTORS = [
338
367
  NotFunctionEvaluator,
339
368
  NilPFunctionEvaluator,
369
+ EqualsPFunctionEvaluator,
340
370
  TagPFunctionEvaluator,
341
371
  CustomFieldValueFunctionEvaluator,
342
372
  CustomFieldGidValueFunctionEvaluator,
@@ -346,6 +376,7 @@ module Checkoff
346
376
  DuePFunctionEvaluator,
347
377
  DueDateSetPFunctionEvaluator,
348
378
  CustomFieldLessThanNDaysFromNowFunctionEvaluator,
379
+ StringLiteralEvaluator,
349
380
  ].freeze
350
381
 
351
382
  # @param task_selector [Array]
@@ -375,13 +406,18 @@ module Checkoff
375
406
  # @param evaluator [FunctionEvaluator]
376
407
  # @return [Boolean, Object, nil]
377
408
  def try_this_evaluator(task_selector, evaluator)
378
- evaluated_args = task_selector[1..].map.with_index do |item, index|
379
- if evaluator.evaluate_arg?(index)
380
- evaluate(item)
381
- else
382
- item
383
- end
384
- end
409
+ # if task_selector is an array
410
+ evaluated_args = if task_selector.is_a?(Array)
411
+ task_selector[1..].map.with_index do |item, index|
412
+ if evaluator.evaluate_arg?(index)
413
+ evaluate(item)
414
+ else
415
+ item
416
+ end
417
+ end
418
+ else
419
+ []
420
+ end
385
421
 
386
422
  evaluator.evaluate(task, *evaluated_args)
387
423
  end
@@ -27,6 +27,17 @@ module Checkoff
27
27
 
28
28
  include Asana::Resources::ResponseHelper
29
29
 
30
+ # @!parse
31
+ # extend CacheMethod::ClassMethods
32
+
33
+ # @param config [Hash<Symbol, Object>]
34
+ # @param workspaces [Checkoff::Workspaces]
35
+ # @param task_selectors [Checkoff::TaskSelectors]
36
+ # @param projects [Checkoff::Projects]
37
+ # @param clients [Checkoff::Clients]
38
+ # @param client [Asana::Client]
39
+ # @param search_url_parser [Checkoff::Internal::SearchUrl::Parser]
40
+ # @param asana_resources_collection_class [Class<Asana::Resources::Collection>]
30
41
  def initialize(config: Checkoff::Internal::ConfigLoader.load(:asana),
31
42
  workspaces: Checkoff::Workspaces.new(config: config),
32
43
  task_selectors: Checkoff::TaskSelectors.new(config: config),
@@ -49,6 +60,7 @@ module Checkoff
49
60
  # @return [Array<Asana::Resources::Task>]
50
61
  def task_search(workspace_name, url, extra_fields: [])
51
62
  workspace = workspaces.workspace_or_raise(workspace_name)
63
+ # @sg-ignore
52
64
  api_params, task_selector = @search_url_parser.convert_params(url)
53
65
  path = "/workspaces/#{workspace.gid}/tasks/search"
54
66
  options = calculate_api_options(extra_fields)
@@ -76,8 +88,13 @@ module Checkoff
76
88
  # bundle exec ./task_searches.rb
77
89
  # :nocov:
78
90
  class << self
91
+ # @return [void]
79
92
  def run
93
+ # @sg-ignore
94
+ # @type [String]
80
95
  workspace_name = ARGV[0] || raise('Please pass workspace name as first argument')
96
+ # @sg-ignore
97
+ # @type [String]
81
98
  url = ARGV[1] || raise('Please pass task search URL as second argument')
82
99
  task_searches = Checkoff::TaskSearches.new
83
100
  task_search = task_searches.task_search(workspace_name, url)
@@ -86,7 +103,14 @@ module Checkoff
86
103
  end
87
104
  # :nocov:
88
105
 
89
- attr_reader :task_selectors, :projects, :workspaces, :client
106
+ # @return [Checkoff::TaskSelectors]
107
+ attr_reader :task_selectors
108
+ # @return [Checkoff::Projects]
109
+ attr_reader :projects
110
+ # @return [Checkoff::Workspaces]
111
+ attr_reader :workspaces
112
+ # @return [Asana::Client]
113
+ attr_reader :client
90
114
  end
91
115
  end
92
116
 
@@ -4,25 +4,25 @@
4
4
 
5
5
  require_relative 'sections'
6
6
  require_relative 'workspaces'
7
+ require_relative 'internal/config_loader'
7
8
  require 'asana'
8
9
 
9
10
  module Checkoff
10
11
  # Pull tasks from Asana
11
12
  class Tasks
12
13
  MINUTE = 60
13
- # @sg-ignore
14
14
  HOUR = MINUTE * 60
15
15
  DAY = 24 * HOUR
16
16
  REALLY_LONG_CACHE_TIME = HOUR
17
- # @sg-ignore
18
17
  LONG_CACHE_TIME = MINUTE * 15
19
- # @sg-ignore
20
18
  SHORT_CACHE_TIME = MINUTE * 5
21
19
 
20
+ # @param config [Hash<Symbol, Object>]
22
21
  # @param client [Asana::Client]
23
22
  # @param workspaces [Checkoff::Workspaces]
24
- # @param time_class [Class<Time>]
25
23
  # @param sections [Checkoff::Sections]
24
+ # @param time_class [Class<Time>]
25
+ # @param asana_task [Class<Asana::Resources::Task>]
26
26
  def initialize(config: Checkoff::Internal::ConfigLoader.load(:asana),
27
27
  client: Checkoff::Clients.new(config: config).client,
28
28
  workspaces: Checkoff::Workspaces.new(config: config,
@@ -39,8 +39,10 @@ module Checkoff
39
39
  @workspaces = workspaces
40
40
  end
41
41
 
42
- def task_ready?(task)
43
- return false if incomplete_dependencies?(task)
42
+ # @param task [Asana::Resources::Task]
43
+ # @param ignore_dependencies [Boolean]
44
+ def task_ready?(task, ignore_dependencies: false)
45
+ return false if !ignore_dependencies && incomplete_dependencies?(task)
44
46
 
45
47
  due = due_time(task)
46
48
 
@@ -50,11 +52,19 @@ module Checkoff
50
52
  end
51
53
 
52
54
  # Pull a specific task by name
55
+ # @param workspace_name [String]
56
+ # @param project_name [String, Symbol]
57
+ # @param section_name [String, nil, Symbol]
58
+ # @param task_name [String]
59
+ # @param only_uncompleted [Boolean]
60
+ # @param extra_fields [Array<String>]
61
+ # @sg-ignore
53
62
  # @return [Asana::Resources::Task, nil]
54
63
  def task(workspace_name, project_name, task_name,
55
64
  section_name: :unspecified,
56
65
  only_uncompleted: true,
57
66
  extra_fields: [])
67
+ # @sg-ignore
58
68
  tasks = tasks_from_section(workspace_name,
59
69
  project_name,
60
70
  section_name: section_name,
@@ -74,6 +84,7 @@ module Checkoff
74
84
  client.tasks.find_by_id(task_gid, options: options)
75
85
  end
76
86
 
87
+ # @param name [String]
77
88
  # @param workspace_gid [String]
78
89
  # @param assignee_gid [String]
79
90
  # @return [Asana::Resources::Task]
@@ -85,13 +96,19 @@ module Checkoff
85
96
  workspace: workspace_gid, name: name)
86
97
  end
87
98
 
88
- # Return an end-user URL to the task in question
99
+ # @param task [Asana::Resources::Task]
100
+ # @return [String] end-user URL to the task in question
89
101
  def url_of_task(task)
90
102
  "https://app.asana.com/0/0/#{task.gid}/f"
91
103
  end
92
104
 
93
105
  private
94
106
 
107
+ # @param workspace_name [String]
108
+ # @param project_name [String, Symbol]
109
+ # @param section_name [String, nil, :unspecified]
110
+ # @param only_uncompleted [Boolean]
111
+ # @param extra_fields [Array<String>]
95
112
  # @return [Array<Asana::Resources::Task>]
96
113
  def tasks_from_section(workspace_name, project_name,
97
114
  section_name:,
@@ -109,6 +126,7 @@ module Checkoff
109
126
  end
110
127
  end
111
128
 
129
+ # @return [Asana::Client]
112
130
  attr_reader :client
113
131
 
114
132
  # @return [Checkoff::Projects]
@@ -131,6 +149,7 @@ module Checkoff
131
149
  nil
132
150
  end
133
151
 
152
+ # @param task [Asana::Resources::Task]
134
153
  def incomplete_dependencies?(task)
135
154
  # Avoid a redundant fetch. Unfortunately, Ruby SDK allows
136
155
  # dependencies to be fetched along with other attributes--but
@@ -3,5 +3,5 @@
3
3
  # Command-line and gem client for Asana (unofficial)
4
4
  module Checkoff
5
5
  # Version of library
6
- VERSION = '0.41.0'
6
+ VERSION = '0.43.0'
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: checkoff
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.41.0
4
+ version: 0.43.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vince Broz
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-06-19 00:00:00.000000000 Z
11
+ date: 2023-06-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport