memra 0.2.14__py3-none-any.whl → 0.2.16__py3-none-any.whl
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.
- memra/__init__.py +1 -1
- memra/cli.py +19 -285
- memra/demos/etl_invoice_processing/etl_invoice_demo.py +4 -2
- {memra-0.2.14.dist-info → memra-0.2.16.dist-info}/METADATA +16 -12
- {memra-0.2.14.dist-info → memra-0.2.16.dist-info}/RECORD +9 -9
- {memra-0.2.14.dist-info → memra-0.2.16.dist-info}/WHEEL +1 -1
- {memra-0.2.14.dist-info → memra-0.2.16.dist-info}/entry_points.txt +0 -0
- {memra-0.2.14.dist-info → memra-0.2.16.dist-info/licenses}/LICENSE +0 -0
- {memra-0.2.14.dist-info → memra-0.2.16.dist-info}/top_level.txt +0 -0
memra/__init__.py
CHANGED
memra/cli.py
CHANGED
@@ -24,9 +24,6 @@ def run_demo():
|
|
24
24
|
print("🔧 Configuring environment...")
|
25
25
|
setup_environment()
|
26
26
|
|
27
|
-
# Step 2.5: Install dependencies
|
28
|
-
install_dependencies()
|
29
|
-
|
30
27
|
# Step 3: Start Docker containers
|
31
28
|
print("🐳 Starting Docker services...")
|
32
29
|
if not start_docker_services(demo_dir):
|
@@ -79,121 +76,15 @@ def setup_demo_environment():
|
|
79
76
|
def extract_bundled_files(demo_dir):
|
80
77
|
"""Extract files bundled with the PyPI package"""
|
81
78
|
try:
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
demo_dir.mkdir(exist_ok=True)
|
88
|
-
|
89
|
-
# Copy the main ETL demo script
|
90
|
-
try:
|
91
|
-
demo_script = pkg_resources.resource_filename('memra', 'demos/etl_invoice_processing/etl_invoice_demo.py')
|
92
|
-
if Path(demo_script).exists():
|
93
|
-
shutil.copy2(demo_script, demo_dir / "etl_invoice_demo.py")
|
94
|
-
print("✅ Copied ETL demo script")
|
95
|
-
else:
|
96
|
-
print("⚠️ ETL demo script not found in package")
|
97
|
-
except Exception as e:
|
98
|
-
print(f"⚠️ Could not copy ETL demo script: {e}")
|
99
|
-
|
100
|
-
# Copy supporting Python files
|
101
|
-
demo_files = [
|
102
|
-
"database_monitor_agent.py",
|
103
|
-
"simple_pdf_processor.py",
|
104
|
-
"setup_demo_data.py"
|
105
|
-
]
|
106
|
-
|
107
|
-
for file_name in demo_files:
|
108
|
-
try:
|
109
|
-
file_path = pkg_resources.resource_filename('memra', f'demos/etl_invoice_processing/{file_name}')
|
110
|
-
if Path(file_path).exists():
|
111
|
-
shutil.copy2(file_path, demo_dir / file_name)
|
112
|
-
print(f"✅ Copied {file_name}")
|
113
|
-
else:
|
114
|
-
print(f"⚠️ {file_name} not found in package")
|
115
|
-
except Exception as e:
|
116
|
-
print(f"⚠️ Could not copy {file_name}: {e}")
|
117
|
-
|
118
|
-
# Copy sample data directory
|
119
|
-
try:
|
120
|
-
data_source = pkg_resources.resource_filename('memra', 'demos/etl_invoice_processing/data')
|
121
|
-
if Path(data_source).exists():
|
122
|
-
data_dir = demo_dir / "data"
|
123
|
-
shutil.copytree(data_source, data_dir, dirs_exist_ok=True)
|
124
|
-
print("✅ Copied sample invoice data")
|
79
|
+
# Extract from package data
|
80
|
+
with pkg_resources.path('memra', 'demo_files') as demo_files_path:
|
81
|
+
if demo_files_path.exists():
|
82
|
+
# Copy all files from the bundled demo_files directory
|
83
|
+
shutil.copytree(demo_files_path, demo_dir, dirs_exist_ok=True)
|
125
84
|
else:
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
# Create memra-ops directory with docker-compose
|
131
|
-
ops_dir = demo_dir / "memra-ops"
|
132
|
-
ops_dir.mkdir(exist_ok=True)
|
133
|
-
|
134
|
-
# Create basic docker-compose.yml
|
135
|
-
compose_content = """version: '3.8'
|
136
|
-
services:
|
137
|
-
postgres:
|
138
|
-
image: postgres:15
|
139
|
-
environment:
|
140
|
-
POSTGRES_DB: local_workflow
|
141
|
-
POSTGRES_USER: postgres
|
142
|
-
POSTGRES_PASSWORD: postgres
|
143
|
-
ports:
|
144
|
-
- "5432:5432"
|
145
|
-
volumes:
|
146
|
-
- postgres_data:/var/lib/postgresql/data
|
147
|
-
|
148
|
-
volumes:
|
149
|
-
postgres_data:
|
150
|
-
"""
|
151
|
-
|
152
|
-
with open(ops_dir / "docker-compose.yml", "w") as f:
|
153
|
-
f.write(compose_content)
|
154
|
-
|
155
|
-
# Create basic MCP bridge server
|
156
|
-
mcp_content = """#!/usr/bin/env python3
|
157
|
-
import asyncio
|
158
|
-
import aiohttp
|
159
|
-
from aiohttp import web
|
160
|
-
import json
|
161
|
-
|
162
|
-
async def health_handler(request):
|
163
|
-
return web.json_response({"status": "healthy"})
|
164
|
-
|
165
|
-
async def execute_tool_handler(request):
|
166
|
-
data = await request.json()
|
167
|
-
tool_name = data.get('tool_name', 'unknown')
|
168
|
-
|
169
|
-
# Mock responses for demo
|
170
|
-
if tool_name == 'SQLExecutor':
|
171
|
-
return web.json_response({
|
172
|
-
"success": True,
|
173
|
-
"results": [{"message": "Demo SQL executed"}]
|
174
|
-
})
|
175
|
-
elif tool_name == 'PostgresInsert':
|
176
|
-
return web.json_response({
|
177
|
-
"success": True,
|
178
|
-
"id": 1
|
179
|
-
})
|
180
|
-
else:
|
181
|
-
return web.json_response({
|
182
|
-
"success": True,
|
183
|
-
"message": f"Demo {tool_name} executed"
|
184
|
-
})
|
185
|
-
|
186
|
-
app = web.Application()
|
187
|
-
app.router.add_get('/health', health_handler)
|
188
|
-
app.router.add_post('/execute_tool', execute_tool_handler)
|
189
|
-
|
190
|
-
if __name__ == '__main__':
|
191
|
-
web.run_app(app, host='0.0.0.0', port=8081)
|
192
|
-
"""
|
193
|
-
|
194
|
-
with open(ops_dir / "mcp_bridge_server.py", "w") as f:
|
195
|
-
f.write(mcp_content)
|
196
|
-
|
85
|
+
# Fallback: create minimal demo structure
|
86
|
+
create_minimal_demo(demo_dir)
|
87
|
+
|
197
88
|
except Exception as e:
|
198
89
|
print(f"⚠️ Could not extract bundled files: {e}")
|
199
90
|
print("Creating minimal demo structure...")
|
@@ -268,41 +159,9 @@ if __name__ == '__main__':
|
|
268
159
|
with open(ops_dir / "mcp_bridge_server.py", "w") as f:
|
269
160
|
f.write(mcp_content)
|
270
161
|
|
271
|
-
#
|
162
|
+
# Create demo workflow
|
272
163
|
demo_dir.mkdir(exist_ok=True)
|
273
|
-
|
274
|
-
|
275
|
-
try:
|
276
|
-
# Try to copy from demos directory
|
277
|
-
source_demo = Path("demos/etl_invoice_processing/etl_invoice_demo.py")
|
278
|
-
if source_demo.exists():
|
279
|
-
# Copy the main demo script
|
280
|
-
shutil.copy2(source_demo, demo_dir / "etl_invoice_demo.py")
|
281
|
-
print("✅ Copied real ETL demo script")
|
282
|
-
|
283
|
-
# Copy all necessary Python dependencies
|
284
|
-
demo_files = [
|
285
|
-
"database_monitor_agent.py",
|
286
|
-
"simple_pdf_processor.py",
|
287
|
-
"setup_demo_data.py"
|
288
|
-
]
|
289
|
-
|
290
|
-
for file_name in demo_files:
|
291
|
-
source_file = Path(f"demos/etl_invoice_processing/{file_name}")
|
292
|
-
if source_file.exists():
|
293
|
-
shutil.copy2(source_file, demo_dir / file_name)
|
294
|
-
print(f"✅ Copied {file_name}")
|
295
|
-
|
296
|
-
# Copy sample data
|
297
|
-
data_dir = demo_dir / "data"
|
298
|
-
data_dir.mkdir(exist_ok=True)
|
299
|
-
source_data = Path("demos/etl_invoice_processing/data")
|
300
|
-
if source_data.exists():
|
301
|
-
shutil.copytree(source_data, data_dir, dirs_exist_ok=True)
|
302
|
-
print("✅ Copied sample invoice data")
|
303
|
-
else:
|
304
|
-
# Create a basic demo if real one not found
|
305
|
-
demo_content = """#!/usr/bin/env python3
|
164
|
+
demo_content = """#!/usr/bin/env python3
|
306
165
|
import os
|
307
166
|
import sys
|
308
167
|
import time
|
@@ -335,47 +194,9 @@ def main():
|
|
335
194
|
if __name__ == "__main__":
|
336
195
|
main()
|
337
196
|
"""
|
338
|
-
with open(demo_dir / "etl_demo.py", "w") as f:
|
339
|
-
f.write(demo_content)
|
340
|
-
print("⚠️ Using simplified demo (real demo not found)")
|
341
|
-
except Exception as e:
|
342
|
-
print(f"Warning: Could not copy ETL demo: {e}")
|
343
|
-
# Fallback to basic demo
|
344
|
-
demo_content = """#!/usr/bin/env python3
|
345
|
-
import os
|
346
|
-
import sys
|
347
|
-
import time
|
348
|
-
|
349
|
-
def main():
|
350
|
-
print("🚀 Starting ETL Invoice Processing Demo...")
|
351
|
-
print("🏢 Starting ETL Invoice Processing Department")
|
352
|
-
print("📋 Mission: Complete end-to-end ETL process with comprehensive monitoring")
|
353
|
-
print("👥 Team: Pre-ETL Database Monitor, Data Engineer, Invoice Parser, Data Entry Specialist, Post-ETL Database Monitor")
|
354
|
-
print("👔 Manager: ETL Process Manager")
|
355
197
|
|
356
|
-
|
357
|
-
(
|
358
|
-
("Data Engineer", "Schema extracted successfully"),
|
359
|
-
("Invoice Parser", "Invoice data extracted: $270.57"),
|
360
|
-
("Data Entry Specialist", "Record inserted: ID 1"),
|
361
|
-
("Post-ETL Database Monitor", "Database state captured: 3 rows")
|
362
|
-
]
|
363
|
-
|
364
|
-
for i, (step, result) in enumerate(steps, 1):
|
365
|
-
print(f"\\n🔄 Step {i}/5: {step}")
|
366
|
-
time.sleep(1)
|
367
|
-
print(f"✅ {result}")
|
368
|
-
|
369
|
-
print("\\n🎉 ETL Invoice Processing Department workflow completed!")
|
370
|
-
print("⏱️ Total time: 5.2s")
|
371
|
-
print("\\n📊 Demo completed successfully!")
|
372
|
-
print("This was a simplified demo. For the full experience, check out the complete ETL workflow.")
|
373
|
-
|
374
|
-
if __name__ == "__main__":
|
375
|
-
main()
|
376
|
-
"""
|
377
|
-
with open(demo_dir / "etl_demo.py", "w") as f:
|
378
|
-
f.write(demo_content)
|
198
|
+
with open(demo_dir / "etl_demo.py", "w") as f:
|
199
|
+
f.write(demo_content)
|
379
200
|
|
380
201
|
def setup_environment():
|
381
202
|
"""Set up environment variables for the demo"""
|
@@ -388,38 +209,6 @@ def setup_environment():
|
|
388
209
|
os.environ['DATABASE_URL'] = 'postgresql://postgres:postgres@localhost:5432/local_workflow'
|
389
210
|
print("✅ Set DATABASE_URL")
|
390
211
|
|
391
|
-
def install_dependencies():
|
392
|
-
"""Install required dependencies for the demo"""
|
393
|
-
try:
|
394
|
-
print("📦 Installing demo dependencies...")
|
395
|
-
dependencies = [
|
396
|
-
'requests==2.31.0',
|
397
|
-
'fastapi==0.104.1',
|
398
|
-
'uvicorn[standard]==0.24.0',
|
399
|
-
'pydantic==2.5.0',
|
400
|
-
'aiohttp',
|
401
|
-
'psycopg2-binary',
|
402
|
-
'httpx',
|
403
|
-
'huggingface_hub'
|
404
|
-
]
|
405
|
-
|
406
|
-
for dep in dependencies:
|
407
|
-
print(f" Installing {dep}...")
|
408
|
-
result = subprocess.run([
|
409
|
-
sys.executable, '-m', 'pip', 'install', dep
|
410
|
-
], capture_output=True, text=True)
|
411
|
-
|
412
|
-
if result.returncode != 0:
|
413
|
-
print(f"⚠️ Warning: Failed to install {dep}: {result.stderr}")
|
414
|
-
else:
|
415
|
-
print(f" ✅ {dep} installed")
|
416
|
-
|
417
|
-
print("✅ Dependencies installed")
|
418
|
-
|
419
|
-
except Exception as e:
|
420
|
-
print(f"⚠️ Warning: Could not install dependencies: {e}")
|
421
|
-
print(" You may need to install them manually: pip install requests fastapi uvicorn pydantic")
|
422
|
-
|
423
212
|
def start_docker_services(demo_dir):
|
424
213
|
"""Start Docker containers using docker-compose"""
|
425
214
|
try:
|
@@ -457,23 +246,9 @@ def wait_for_services():
|
|
457
246
|
"""Wait for services to be ready"""
|
458
247
|
print("⏳ Waiting for PostgreSQL to be ready...")
|
459
248
|
|
460
|
-
# Wait for PostgreSQL
|
249
|
+
# Wait for PostgreSQL
|
461
250
|
for i in range(30): # Wait up to 30 seconds
|
462
251
|
try:
|
463
|
-
# Try the memra-ops container name first
|
464
|
-
result = subprocess.run([
|
465
|
-
'docker', 'exec', 'memra-ops_postgres_1',
|
466
|
-
'pg_isready', '-U', 'postgres', '-d', 'local_workflow'
|
467
|
-
], capture_output=True, text=True)
|
468
|
-
|
469
|
-
if result.returncode == 0:
|
470
|
-
print("✅ PostgreSQL is ready")
|
471
|
-
break
|
472
|
-
except:
|
473
|
-
pass
|
474
|
-
|
475
|
-
try:
|
476
|
-
# Fallback to the old container name
|
477
252
|
result = subprocess.run([
|
478
253
|
'docker', 'exec', 'memra_postgres',
|
479
254
|
'pg_isready', '-U', 'postgres', '-d', 'local_workflow'
|
@@ -494,56 +269,15 @@ def wait_for_services():
|
|
494
269
|
def run_etl_workflow(demo_dir):
|
495
270
|
"""Run the ETL workflow"""
|
496
271
|
try:
|
497
|
-
#
|
498
|
-
|
499
|
-
if
|
500
|
-
|
501
|
-
print(f"📁 Working directory: {demo_dir}")
|
502
|
-
print(f"📄 Demo script: {real_demo_script}")
|
503
|
-
|
504
|
-
# Check if data directory exists
|
505
|
-
data_dir = demo_dir / "data"
|
506
|
-
invoices_dir = data_dir / "invoices"
|
507
|
-
if invoices_dir.exists():
|
508
|
-
pdf_files = list(invoices_dir.glob("*.PDF"))
|
509
|
-
print(f"📊 Found {len(pdf_files)} PDF files in {invoices_dir}")
|
510
|
-
if pdf_files:
|
511
|
-
print(f" First few files: {[f.name for f in pdf_files[:3]]}")
|
512
|
-
else:
|
513
|
-
print(f"⚠️ Warning: {invoices_dir} does not exist")
|
514
|
-
print(f" Available directories in {demo_dir}:")
|
515
|
-
for item in demo_dir.iterdir():
|
516
|
-
if item.is_dir():
|
517
|
-
print(f" - {item.name}/")
|
518
|
-
|
519
|
-
print("⏱️ Processing 15 files with delays - this may take 10-15 minutes")
|
520
|
-
|
521
|
-
# Set the working directory to the demo directory so the script can find data/invoices/
|
522
|
-
result = subprocess.run(
|
523
|
-
[sys.executable, str(real_demo_script)],
|
524
|
-
cwd=demo_dir, # This is crucial - sets working directory
|
525
|
-
timeout=1800 # 30 minute timeout
|
526
|
-
)
|
272
|
+
# Run the demo script
|
273
|
+
demo_script = demo_dir / "etl_demo.py"
|
274
|
+
if demo_script.exists():
|
275
|
+
result = subprocess.run([sys.executable, str(demo_script)], cwd=demo_dir)
|
527
276
|
return result.returncode == 0
|
528
277
|
else:
|
529
|
-
|
530
|
-
|
531
|
-
if demo_script.exists():
|
532
|
-
print("🎯 Running simplified demo...")
|
533
|
-
result = subprocess.run([sys.executable, str(demo_script)], cwd=demo_dir)
|
534
|
-
return result.returncode == 0
|
535
|
-
else:
|
536
|
-
print("❌ No demo script found")
|
537
|
-
print(f" Looking for: {real_demo_script}")
|
538
|
-
print(f" Available files in {demo_dir}:")
|
539
|
-
for item in demo_dir.iterdir():
|
540
|
-
print(f" - {item.name}")
|
541
|
-
return False
|
278
|
+
print("❌ Demo script not found")
|
279
|
+
return False
|
542
280
|
|
543
|
-
except subprocess.TimeoutExpired:
|
544
|
-
print("⏰ ETL workflow timed out after 30 minutes")
|
545
|
-
print("This is normal for large batches - the demo processes 15 files with delays")
|
546
|
-
return False
|
547
281
|
except Exception as e:
|
548
282
|
print(f"❌ Error running ETL workflow: {e}")
|
549
283
|
return False
|
@@ -791,8 +791,10 @@ def process_database_insertion(agent, tool_results, **kwargs):
|
|
791
791
|
# Inject the properly formatted data into the tool parameters
|
792
792
|
if 'parameters' not in result:
|
793
793
|
result['parameters'] = {}
|
794
|
-
|
795
|
-
|
794
|
+
# Pass the data in the format expected by PostgresInsert tool
|
795
|
+
result['parameters']['invoice_data'] = invoice_data # Pass the original invoice_data
|
796
|
+
result['parameters']['table_name'] = 'invoices'
|
797
|
+
print(f"\n✅ [AGENT 4] Injected invoice_data into PostgresInsert parameters")
|
796
798
|
|
797
799
|
# Call the original print function for debugging
|
798
800
|
print_database_data(agent, tool_results, invoice_data)
|
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: memra
|
3
|
-
Version: 0.2.
|
3
|
+
Version: 0.2.16
|
4
4
|
Summary: Declarative framework for enterprise workflows with MCP integration - Client SDK
|
5
5
|
Home-page: https://github.com/memra/memra-sdk
|
6
6
|
Author: Memra
|
@@ -20,18 +20,22 @@ Classifier: Programming Language :: Python :: 3.11
|
|
20
20
|
Requires-Python: >=3.8
|
21
21
|
Description-Content-Type: text/markdown
|
22
22
|
License-File: LICENSE
|
23
|
-
Requires-Dist: pydantic
|
24
|
-
Requires-Dist: httpx
|
25
|
-
Requires-Dist: typing-extensions
|
26
|
-
Requires-Dist: aiohttp
|
27
|
-
Requires-Dist: aiohttp-cors
|
23
|
+
Requires-Dist: pydantic>=1.8.0
|
24
|
+
Requires-Dist: httpx>=0.24.0
|
25
|
+
Requires-Dist: typing-extensions>=4.0.0
|
26
|
+
Requires-Dist: aiohttp>=3.8.0
|
27
|
+
Requires-Dist: aiohttp-cors>=0.7.0
|
28
28
|
Provides-Extra: dev
|
29
|
-
Requires-Dist: pytest
|
30
|
-
Requires-Dist: pytest-asyncio
|
31
|
-
Requires-Dist: black
|
32
|
-
Requires-Dist: flake8
|
29
|
+
Requires-Dist: pytest>=6.0; extra == "dev"
|
30
|
+
Requires-Dist: pytest-asyncio; extra == "dev"
|
31
|
+
Requires-Dist: black; extra == "dev"
|
32
|
+
Requires-Dist: flake8; extra == "dev"
|
33
33
|
Provides-Extra: mcp
|
34
|
-
Requires-Dist: psycopg2-binary
|
34
|
+
Requires-Dist: psycopg2-binary>=2.9.0; extra == "mcp"
|
35
|
+
Dynamic: author
|
36
|
+
Dynamic: home-page
|
37
|
+
Dynamic: license-file
|
38
|
+
Dynamic: requires-python
|
35
39
|
|
36
40
|
# Memra SDK
|
37
41
|
|
@@ -1,5 +1,5 @@
|
|
1
|
-
memra/__init__.py,sha256=
|
2
|
-
memra/cli.py,sha256=
|
1
|
+
memra/__init__.py,sha256=DEOu1dmnPnJWyfCgmarnjSFZZSgiUiv3VdGA7thdxYs,1109
|
2
|
+
memra/cli.py,sha256=DSkgwlko8NqUMdXxt-_Y7hMdqMGkGmF6PuzhQqCyjto,10310
|
3
3
|
memra/discovery.py,sha256=yJIQnrDQu1nyzKykCIuzG_5SW5dIXHCEBLLKRWacIoY,480
|
4
4
|
memra/discovery_client.py,sha256=AbnKn6qhyrf7vmOvknEeDzH4tiGHsqPHtDaein_qaW0,1271
|
5
5
|
memra/execution.py,sha256=OXpBKxwBIjhACWL_qh8KHNndO8HUgB6gBF81AiQBBm0,34751
|
@@ -12,7 +12,7 @@ memra/demos/etl_invoice_processing/check_recent_db.py,sha256=tyO47DfwJkFH6IsdoM7
|
|
12
12
|
memra/demos/etl_invoice_processing/database_monitor_agent.py,sha256=_A2mqweJTDOtbf57GCt20F5JG8RoH2UyUxET104dgAI,3497
|
13
13
|
memra/demos/etl_invoice_processing/debug_mcp.py,sha256=xga1xzI0wycqF7aF5dsp3bL_o8aTnBYjOH0ZnjUZUtM,2066
|
14
14
|
memra/demos/etl_invoice_processing/debug_schema.py,sha256=zirxgrgEtvE56oLNXvk4rL_kopIT53fIviKUQg1Ise4,1416
|
15
|
-
memra/demos/etl_invoice_processing/etl_invoice_demo.py,sha256=
|
15
|
+
memra/demos/etl_invoice_processing/etl_invoice_demo.py,sha256=_ogkYQpiG95a1Sc-JCgjP9zRp8HbPQL_wlc2LHIFXCE,52998
|
16
16
|
memra/demos/etl_invoice_processing/modify_database.py,sha256=qHzBf8ukeHouaOsy0kjsfR00xCbvPUOrt1gwc4y7Xkc,1939
|
17
17
|
memra/demos/etl_invoice_processing/run_etl_batch.py,sha256=czX-gfUuVnYb1ZjzirK7w9aa1fAUuIRCs3044AucT_Y,1928
|
18
18
|
memra/demos/etl_invoice_processing/setup_demo_data.py,sha256=aeOZtFBBl5SZFZ5IqM35Tcc_PjEJHuc2cfY_LRWXkBM,4875
|
@@ -58,9 +58,9 @@ memra/demos/etl_invoice_processing/data/invoices/10352262702.PDF,sha256=aNWnxbYq
|
|
58
58
|
memra/demos/etl_invoice_processing/data/invoices/10352262884.PDF,sha256=G0eszEhpTOS15hIlMyPMM6iyVw6UZPKycXvS3P42xRc,1010830
|
59
59
|
memra/demos/etl_invoice_processing/data/invoices/10352263346.PDF,sha256=NMfsgrmaNtvNu6xk2aLtubI05I9cuVIbwJMxv_pYPhQ,1089624
|
60
60
|
memra/demos/etl_invoice_processing/data/invoices/10352263429.PDF,sha256=1IzJbmnsKDE1cV6CtyNMENn0Rmpq2tA_BDnZYTYhNhQ,1082893
|
61
|
-
memra-0.2.
|
62
|
-
memra-0.2.
|
63
|
-
memra-0.2.
|
64
|
-
memra-0.2.
|
65
|
-
memra-0.2.
|
66
|
-
memra-0.2.
|
61
|
+
memra-0.2.16.dist-info/licenses/LICENSE,sha256=8OrnTd8DWwLWmUEj5srSLvT4PREfW1Qo1T5gEUIHPws,1062
|
62
|
+
memra-0.2.16.dist-info/METADATA,sha256=u-MAjWfwdJ9f79TA7SSGouLxrKm-RDkX12GsXR-HnXI,9497
|
63
|
+
memra-0.2.16.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
64
|
+
memra-0.2.16.dist-info/entry_points.txt,sha256=LBVjwWoxWJRzNLgeByPn6xUvWFIRnqnemvAZgIoSt08,41
|
65
|
+
memra-0.2.16.dist-info/top_level.txt,sha256=pXWcTRS1zctdiSUivW4iyKpJ4tcfIu-1BW_fpbal3OY,6
|
66
|
+
memra-0.2.16.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|