rospatent 1.4.1 → 1.5.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: 02b32bdfdedb6dd788856f5335d17ed7c739449e111fc72ea96cc8768bbe47a8
4
- data.tar.gz: 1de3f7131127a1b68e69e99c370abe67825c922ac511e26c0e99ca0440969cfb
3
+ metadata.gz: 4a3938079b33ac5c291c85501df526ec12b7721a91c9f7c9a4b5c35c56a8fdab
4
+ data.tar.gz: 2a8cb80112a1c0380f2dd15f2e3e4909ae37f84e7ef3a819aa9d86fce6d1e765
5
5
  SHA512:
6
- metadata.gz: fcc95897171c5b6f7edbd10209a806b7cac6c19254fdc9c96176479c6f2b6cb284446089b2ca39f57e20ef7bd7484500b570498884f45c0321da76eb6e299723
7
- data.tar.gz: 392587596ad48ecbc5d65ee54f8c518c388315137a1dbbebb00dc2728ea9a5011157afceb679e2939e0350b8e48a43e50f961d07328a20e5d2d77c8325e43644
6
+ metadata.gz: 8843ca4bd8c87de711bed059c9f315a8d46a6123c0763a3eb7dcbfc5af6512e1d35b03782a22b37eb74578942592cb699b4ab8eb07c7744f651230b950c03e41
7
+ data.tar.gz: 29896e1b71030d368a54fc4d40bc3a9cd79318b82089618f71e98eafee65ce266d781dd2d1518001e0bd388af0937f2d46a5c7f911673d155738fa61e48fda44
data/CHANGELOG.md CHANGED
@@ -5,10 +5,53 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.5.0] - 2025-06-09
9
+
10
+ ### Added
11
+ - **Configurable Validation Limits**: Major enhancement to configuration system with customizable validation thresholds
12
+ - New `validation_limits` hash in configuration with 16 configurable parameters
13
+ - Users can now customize query length limits, pagination limits, array sizes, and more
14
+ - Fine-grained control over validation behavior without code modifications
15
+ - Environment-specific validation tuning support
16
+ - **Comprehensive Validation Configuration**: All validation limits now centralized and configurable
17
+ - Query parameters: `query_max_length`, `natural_query_max_length` (default: 2000)
18
+ - Pagination: `limit_max_value` (default: 100), `offset_max_value` (default: 10,000)
19
+ - Arrays: `array_max_size` (default: 10), various tag limits
20
+ - Classification: `classification_query_max_length`, `classification_code_max_length`
21
+ - Similar search: `similar_text_min_words`, `similar_text_max_length`, `similar_count_max_value`
22
+ - Batch operations: `batch_size_max_value`, `batch_ids_max_size`
23
+
24
+ ### Changed
25
+ - **Consolidated Validation Logic**: Eliminated code duplication by centralizing validation in Search class
26
+ - Removed duplicate validation limits from Client class
27
+ - All validation now happens in single location (Search class)
28
+ - Improved maintainability and reduced code duplication
29
+ - **Enhanced Configuration System**: Extended configuration to support nested validation limits
30
+ - Configuration now supports hash-based validation limits
31
+ - All validation methods updated to use configurable limits
32
+ - Backward compatible configuration structure
33
+
34
+ ### Deprecated
35
+ - **Client#validate_search_params**: Method deprecated in favor of centralized validation
36
+ - Method now returns parameters as-is for backward compatibility
37
+ - Validation responsibility moved to Search class
38
+ - Marked with deprecation notice for future removal
39
+
40
+ ### Fixed
41
+ - **Validation Duplication**: Resolved issue where validation limits were hardcoded in multiple places
42
+ - Single source of truth for validation configuration
43
+ - Easier maintenance when API specifications change
44
+ - Consistent validation behavior across all methods
45
+
46
+ ## [1.4.2] - 2025-07-15
47
+
48
+ ## Fixed
49
+ Updated the maximum length for the q and qn query parameters from 1000 to 2000 to accommodate larger input values in `Rospatent::Client#validate_search_params`.
50
+
8
51
  ## [1.4.1] - 2025-07-15
9
52
 
10
53
  ## Fixed
11
- Updated the maximum length for the q and qn query parameters from 1000 to 2000 to accommodate larger input values.
54
+ Updated the maximum length for the q and qn query parameters from 1000 to 2000 to accommodate larger input values in `Rospatent::Search#validate_and_normalize_params`.
12
55
 
13
56
  ## [1.4.0] - 2025-06-09
14
57
 
data/README.md CHANGED
@@ -11,7 +11,7 @@ A comprehensive Ruby client for the Rospatent patent search API with advanced fe
11
11
  - 🔍 **Complete API Coverage** - Search, retrieve patents, media files, and datasets
12
12
  - 🛡️ **Robust Error Handling** - Comprehensive error types with detailed context
13
13
  - ⚡ **Intelligent Caching** - In-memory caching with TTL and LRU eviction
14
- - ✅ **Input Validation** - Automatic parameter validation with helpful error messages
14
+ - ✅ **Input Validation** - Automatic parameter validation with configurable limits and helpful error messages
15
15
  - 📊 **Structured Logging** - JSON/text logging with request/response tracking
16
16
  - 🚀 **Batch Operations** - Process multiple patents concurrently
17
17
  - ⚙️ **Environment-Aware** - Different configurations for dev/staging/production
@@ -101,6 +101,56 @@ Rospatent.configure do |config|
101
101
  end
102
102
  ```
103
103
 
104
+ ### Validation Limits Configuration
105
+
106
+ Customize validation thresholds for different parameters to suit your specific needs:
107
+
108
+ ```ruby
109
+ Rospatent.configure do |config|
110
+ config.token = "your_jwt_token"
111
+
112
+ # Customize validation limits
113
+ config.validation_limits = {
114
+ # Query parameters
115
+ query_max_length: 5000, # Default: 2000
116
+ natural_query_max_length: 3000, # Default: 2000
117
+
118
+ # Pagination limits
119
+ limit_max_value: 200, # Default: 100
120
+ offset_max_value: 50_000, # Default: 10,000
121
+
122
+ # Array and string limits
123
+ array_max_size: 20, # Default: 10
124
+ string_max_length: 2000, # Default: 1000
125
+
126
+ # Highlighting limits
127
+ pre_tag_max_length: 100, # Default: 50
128
+ post_tag_max_length: 100, # Default: 50
129
+ pre_tag_max_size: 20, # Default: 10
130
+ post_tag_max_size: 20, # Default: 10
131
+
132
+ # Classification search limits
133
+ classification_query_max_length: 2000, # Default: 1000
134
+ classification_code_max_length: 100, # Default: 50
135
+
136
+ # Similar search limits
137
+ similar_text_min_words: 30, # Default: 50
138
+ similar_text_max_length: 20_000, # Default: 10,000
139
+ similar_count_max_value: 2000, # Default: 1000
140
+
141
+ # Batch operation limits
142
+ batch_size_max_value: 100, # Default: 50
143
+ batch_ids_max_size: 2000 # Default: 1000
144
+ }
145
+ end
146
+ ```
147
+
148
+ **Benefits of configurable validation limits:**
149
+ - **Flexibility**: Adjust limits based on your application's requirements
150
+ - **Performance**: Fine-tune validation for optimal performance
151
+ - **API Evolution**: Easily adapt to changes in Rospatent API specifications
152
+ - **Environment-specific**: Different limits for development, staging, and production
153
+
104
154
  ### Environment-Specific Configuration
105
155
 
106
156
  The gem automatically adjusts settings based on environment with sensible defaults:
@@ -1126,7 +1176,7 @@ $ bundle exec rake release
1126
1176
  - 🔍 **Полное покрытие API** - поиск, получение патентов, медиафайлы и датасеты
1127
1177
  - 🛡️ **Надежная обработка ошибок** - комплексные типы ошибок с детальным контекстом
1128
1178
  - ⚡ **Интеллектуальное кеширование** - кеширование в памяти с TTL и LRU исключением
1129
- - ✅ **Валидация входных данных** - автоматическая валидация параметров с полезными сообщениями
1179
+ - ✅ **Валидация входных данных** - автоматическая валидация параметров с настраиваемыми лимитами и полезными сообщениями
1130
1180
  - 📊 **Структурированное логирование** - JSON/текстовое логирование с отслеживанием запросов/ответов
1131
1181
  - 🚀 **Пакетные операции** - параллельная обработка множества патентов
1132
1182
  - ⚙️ **Адаптивные окружения** - различные конфигурации для development/staging/production
@@ -1215,6 +1265,56 @@ Rospatent.configure do |config|
1215
1265
  end
1216
1266
  ```
1217
1267
 
1268
+ ### Конфигурация лимитов валидации
1269
+
1270
+ Настройте пороговые значения валидации для различных параметров в соответствии с вашими потребностями:
1271
+
1272
+ ```ruby
1273
+ Rospatent.configure do |config|
1274
+ config.token = "ваш_jwt_токен"
1275
+
1276
+ # Настройка лимитов валидации
1277
+ config.validation_limits = {
1278
+ # Параметры запросов
1279
+ query_max_length: 5000, # По умолчанию: 2000
1280
+ natural_query_max_length: 3000, # По умолчанию: 2000
1281
+
1282
+ # Лимиты пагинации
1283
+ limit_max_value: 200, # По умолчанию: 100
1284
+ offset_max_value: 50_000, # По умолчанию: 10,000
1285
+
1286
+ # Лимиты массивов и строк
1287
+ array_max_size: 20, # По умолчанию: 10
1288
+ string_max_length: 2000, # По умолчанию: 1000
1289
+
1290
+ # Лимиты подсветки
1291
+ pre_tag_max_length: 100, # По умолчанию: 50
1292
+ post_tag_max_length: 100, # По умолчанию: 50
1293
+ pre_tag_max_size: 20, # По умолчанию: 10
1294
+ post_tag_max_size: 20, # По умолчанию: 10
1295
+
1296
+ # Лимиты поиска по классификации
1297
+ classification_query_max_length: 2000, # По умолчанию: 1000
1298
+ classification_code_max_length: 100, # По умолчанию: 50
1299
+
1300
+ # Лимиты поиска похожих патентов
1301
+ similar_text_min_words: 30, # По умолчанию: 50
1302
+ similar_text_max_length: 20_000, # По умолчанию: 10,000
1303
+ similar_count_max_value: 2000, # По умолчанию: 1000
1304
+
1305
+ # Лимиты пакетных операций
1306
+ batch_size_max_value: 100, # По умолчанию: 50
1307
+ batch_ids_max_size: 2000 # По умолчанию: 1000
1308
+ }
1309
+ end
1310
+ ```
1311
+
1312
+ **Преимущества настраиваемых лимитов валидации:**
1313
+ - **Гибкость**: Настройка лимитов в соответствии с требованиями вашего приложения
1314
+ - **Производительность**: Точная настройка валидации для оптимальной производительности
1315
+ - **Эволюция API**: Легкая адаптация к изменениям в спецификациях API Роспатента
1316
+ - **Специфичность окружения**: Различные лимиты для разработки, staging и продакшна
1317
+
1218
1318
  ### Конфигурация для конкретных окружений
1219
1319
 
1220
1320
  Gem автоматически настраивается под окружение с разумными значениями по умолчанию:
@@ -35,9 +35,8 @@ module Rospatent
35
35
  # @param params [Hash] Search parameters
36
36
  # @return [Rospatent::SearchResult] Search result object
37
37
  def search(**params)
38
- # Validate search parameters
39
- validated_params = validate_search_params(params)
40
- Search.new(self).execute(**validated_params)
38
+ # Validation is now handled by Search class to avoid duplication
39
+ Search.new(self).execute(**params)
41
40
  end
42
41
 
43
42
  # Fetch a specific patent by its document ID using dedicated endpoint
@@ -117,7 +116,7 @@ module Rospatent
117
116
  def similar_patents_by_id(document_id, count: 100)
118
117
  # Validate inputs
119
118
  validated_id = validate_patent_id(document_id)
120
- validated_count = validate_positive_integer(count, "count", max_value: 1000)
119
+ validated_count = validate_positive_integer(count, "count", max_value: Rospatent.configuration.validation_limits[:similar_count_max_value])
121
120
 
122
121
  # Check cache first
123
122
  cache_key = "similar:id:#{validated_id}:#{validated_count}"
@@ -153,9 +152,10 @@ module Rospatent
153
152
  # @raise [Rospatent::Errors::ValidationError] If text has insufficient words or errors
154
153
  def similar_patents_by_text(text, count: 100)
155
154
  # Validate inputs - text must have at least 50 words for the API
156
- validated_text = validate_text_with_word_count(text, "search_text", min_words: 50,
157
- max_length: 10_000)
158
- validated_count = validate_positive_integer(count, "count", max_value: 1000)
155
+ validated_text = validate_text_with_word_count(text, "search_text",
156
+ min_words: Rospatent.configuration.validation_limits[:similar_text_min_words],
157
+ max_length: Rospatent.configuration.validation_limits[:similar_text_max_length])
158
+ validated_count = validate_positive_integer(count, "count", max_value: Rospatent.configuration.validation_limits[:similar_count_max_value])
159
159
 
160
160
  # Check cache first (using hash of text for key)
161
161
  text_hash = validated_text.hash.abs.to_s(16)
@@ -337,7 +337,7 @@ module Rospatent
337
337
  def classification_search(classifier_id, query:, lang: "ru")
338
338
  # Validate inputs
339
339
  validated_classifier = validate_enum(classifier_id, %w[ipc cpc], "classifier_id").to_s
340
- validated_query = validate_string(query, "query", max_length: 1000)
340
+ validated_query = validate_string(query, "query", max_length: Rospatent.configuration.validation_limits[:classification_query_max_length])
341
341
  validated_lang = validate_enum(lang, %w[ru en], "lang").to_s
342
342
 
343
343
  # Check cache first
@@ -378,7 +378,7 @@ module Rospatent
378
378
  def classification_code(classifier_id, code:, lang: "ru")
379
379
  # Validate inputs
380
380
  validated_classifier = validate_enum(classifier_id, %w[ipc cpc], "classifier_id").to_s
381
- validated_code = validate_string(code, "code", max_length: 50)
381
+ validated_code = validate_string(code, "code", max_length: Rospatent.configuration.validation_limits[:classification_code_max_length])
382
382
  validated_lang = validate_enum(lang, %w[ru en], "lang").to_s
383
383
 
384
384
  # Check cache first
@@ -482,8 +482,8 @@ module Rospatent
482
482
  def batch_patents(document_ids, batch_size: 10)
483
483
  return enum_for(:batch_patents, document_ids, batch_size: batch_size) unless block_given?
484
484
 
485
- validate_array(document_ids, "document_ids", max_size: 1000)
486
- validated_batch_size = validate_positive_integer(batch_size, "batch_size", max_value: 50)
485
+ validate_array(document_ids, "document_ids", max_size: Rospatent.configuration.validation_limits[:batch_ids_max_size])
486
+ validated_batch_size = validate_positive_integer(batch_size, "batch_size", max_value: Rospatent.configuration.validation_limits[:batch_size_max_value])
487
487
 
488
488
  document_ids.each_slice(validated_batch_size) do |batch|
489
489
  threads = batch.map do |doc_id|
@@ -542,23 +542,11 @@ module Rospatent
542
542
  # Validate search parameters
543
543
  # @param params [Hash] Search parameters to validate
544
544
  # @return [Hash] Validated parameters
545
+ # @deprecated This method is deprecated. Validation now happens in Search class.
545
546
  def validate_search_params(params)
546
- validations = {
547
- q: { type: :string, max_length: 1000 },
548
- qn: { type: :string, max_length: 1000 },
549
- limit: { type: :positive_integer, min_value: 1, max_value: 100 },
550
- offset: { type: :positive_integer, min_value: 0, max_value: 10_000 },
551
- pre_tag: { type: :string_or_array, max_length: 50, max_size: 10 },
552
- post_tag: { type: :string_or_array, max_length: 50, max_size: 10 },
553
- sort: { type: :enum, allowed_values: %i[relevance pub_date filing_date] },
554
- group_by: { type: :string_enum, allowed_values: %w[family:docdb family:dwpi] },
555
- include_facets: { type: :boolean },
556
- highlight: { type: :hash },
557
- filter: { type: :filter },
558
- datasets: { type: :array, max_size: 10 }
559
- }
560
-
561
- validate_params(params, validations)
547
+ # Validation is now handled by Search class to avoid duplication
548
+ # This method remains for backward compatibility but does no validation
549
+ params
562
550
  end
563
551
 
564
552
  # Parse a patent ID string into its component parts
@@ -27,6 +27,8 @@ module Rospatent
27
27
  attr_accessor :token_expires_at, :token_refresh_callback
28
28
  # Connection pooling
29
29
  attr_accessor :connection_pool_size, :connection_keep_alive
30
+ # Validation limits
31
+ attr_accessor :validation_limits
30
32
 
31
33
  # Initialize a new configuration with default values
32
34
  def initialize
@@ -57,6 +59,27 @@ module Rospatent
57
59
  @connection_pool_size = ENV.fetch("ROSPATENT_POOL_SIZE", "5").to_i
58
60
  @connection_keep_alive = ENV.fetch("ROSPATENT_KEEP_ALIVE", "true") == "true"
59
61
 
62
+ # Validation limits
63
+ @validation_limits = {
64
+ query_max_length: 2000,
65
+ natural_query_max_length: 2000,
66
+ limit_max_value: 100,
67
+ offset_max_value: 10_000,
68
+ array_max_size: 10,
69
+ string_max_length: 1000,
70
+ pre_tag_max_length: 50,
71
+ post_tag_max_length: 50,
72
+ pre_tag_max_size: 10,
73
+ post_tag_max_size: 10,
74
+ classification_query_max_length: 1000,
75
+ classification_code_max_length: 50,
76
+ similar_text_min_words: 50,
77
+ similar_text_max_length: 10_000,
78
+ similar_count_max_value: 1000,
79
+ batch_size_max_value: 50,
80
+ batch_ids_max_size: 1000
81
+ }
82
+
60
83
  load_environment_config
61
84
  end
62
85
 
@@ -97,17 +97,18 @@ module Rospatent
97
97
  validated = {}
98
98
 
99
99
  # Validate query parameters
100
- validated[:q] = validate_string(params[:q], "q", max_length: 2000) if params[:q]
101
- validated[:qn] = validate_string(params[:qn], "qn", max_length: 2000) if params[:qn]
100
+ config = Rospatent.configuration
101
+ validated[:q] = validate_string(params[:q], "q", max_length: config.validation_limits[:query_max_length]) if params[:q]
102
+ validated[:qn] = validate_string(params[:qn], "qn", max_length: config.validation_limits[:natural_query_max_length]) if params[:qn]
102
103
 
103
104
  # Validate pagination parameters (only if provided)
104
105
  if params[:limit]
105
106
  validated[:limit] =
106
- validate_positive_integer(params[:limit], "limit", min_value: 1, max_value: 100)
107
+ validate_positive_integer(params[:limit], "limit", min_value: 1, max_value: config.validation_limits[:limit_max_value])
107
108
  end
108
109
  if params[:offset]
109
110
  validated[:offset] =
110
- validate_positive_integer(params[:offset], "offset", min_value: 0, max_value: 10_000)
111
+ validate_positive_integer(params[:offset], "offset", min_value: 0, max_value: config.validation_limits[:offset_max_value])
111
112
  end
112
113
 
113
114
  # Validate highlighting parameters (only if provided)
@@ -119,9 +120,9 @@ module Rospatent
119
120
  end
120
121
 
121
122
  validated[:pre_tag] =
122
- validate_string_or_array(params[:pre_tag], "pre_tag", max_length: 50, max_size: 10)
123
+ validate_string_or_array(params[:pre_tag], "pre_tag", max_length: config.validation_limits[:pre_tag_max_length], max_size: config.validation_limits[:pre_tag_max_size])
123
124
  validated[:post_tag] =
124
- validate_string_or_array(params[:post_tag], "post_tag", max_length: 50, max_size: 10)
125
+ validate_string_or_array(params[:post_tag], "post_tag", max_length: config.validation_limits[:post_tag_max_length], max_size: config.validation_limits[:post_tag_max_size])
125
126
  end
126
127
 
127
128
  # Validate highlight parameter (complex object for advanced highlighting)
@@ -152,7 +153,7 @@ module Rospatent
152
153
 
153
154
  # Validate datasets parameter
154
155
  if params[:datasets]
155
- validated[:datasets] = validate_array(params[:datasets], "datasets", max_size: 10) do |dataset|
156
+ validated[:datasets] = validate_array(params[:datasets], "datasets", max_size: config.validation_limits[:array_max_size]) do |dataset|
156
157
  validate_string(dataset, "dataset")
157
158
  end
158
159
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rospatent
4
- VERSION = "1.4.1"
4
+ VERSION = "1.5.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rospatent
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.1
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aleksandr Dryzhuk