geoseeq 0.7.1__tar.gz → 0.7.2__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 (142) hide show
  1. {geoseeq-0.7.1 → geoseeq-0.7.2}/PKG-INFO +6 -1
  2. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/cli/main.py +1 -1
  3. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/cli/upload/upload.py +2 -2
  4. {geoseeq-0.7.1 → geoseeq-0.7.2}/pyproject.toml +14 -1
  5. geoseeq-0.7.2/tests/conftest.py +55 -0
  6. geoseeq-0.7.2/tests/test_download.py +104 -0
  7. geoseeq-0.7.2/tests/test_download_cli.py +124 -0
  8. geoseeq-0.7.2/tests/test_upload.py +76 -0
  9. geoseeq-0.7.2/tests/test_upload_cli.py +112 -0
  10. {geoseeq-0.7.1 → geoseeq-0.7.2}/.github/workflows/python-publish.yml +0 -0
  11. {geoseeq-0.7.1 → geoseeq-0.7.2}/.github/workflows/run_unit_tests.yml +0 -0
  12. {geoseeq-0.7.1 → geoseeq-0.7.2}/.gitignore +0 -0
  13. {geoseeq-0.7.1 → geoseeq-0.7.2}/.pre-commit-config.yaml +0 -0
  14. {geoseeq-0.7.1 → geoseeq-0.7.2}/.vscode/settings.json +0 -0
  15. {geoseeq-0.7.1 → geoseeq-0.7.2}/GCF_036600855.1_ASM3660085v1_genomic.fna.gz +0 -0
  16. {geoseeq-0.7.1 → geoseeq-0.7.2}/LICENSE +0 -0
  17. {geoseeq-0.7.1 → geoseeq-0.7.2}/Makefile +0 -0
  18. {geoseeq-0.7.1 → geoseeq-0.7.2}/README.md +0 -0
  19. {geoseeq-0.7.1 → geoseeq-0.7.2}/commit_pylintrc +0 -0
  20. {geoseeq-0.7.1 → geoseeq-0.7.2}/dashtest.py +0 -0
  21. {geoseeq-0.7.1 → geoseeq-0.7.2}/docs/about_geoseeq.md +0 -0
  22. {geoseeq-0.7.1 → geoseeq-0.7.2}/docs/contributing.md +0 -0
  23. {geoseeq-0.7.1 → geoseeq-0.7.2}/docs/downloading_data_examples.md +0 -0
  24. {geoseeq-0.7.1 → geoseeq-0.7.2}/docs/examples/simple_python_example/README.md +0 -0
  25. {geoseeq-0.7.1 → geoseeq-0.7.2}/docs/examples/simple_python_example/simple_python_example.py +0 -0
  26. {geoseeq-0.7.1 → geoseeq-0.7.2}/docs/examples/simple_python_example/smart_table_example.py +0 -0
  27. {geoseeq-0.7.1 → geoseeq-0.7.2}/docs/examples/simple_snakemake_example/README.md +0 -0
  28. {geoseeq-0.7.1 → geoseeq-0.7.2}/docs/examples/simple_snakemake_example/Snakefile +0 -0
  29. {geoseeq-0.7.1 → geoseeq-0.7.2}/docs/examples/simple_snakemake_example/config.yaml +0 -0
  30. {geoseeq-0.7.1 → geoseeq-0.7.2}/docs/uploading_data_examples.md +0 -0
  31. {geoseeq-0.7.1 → geoseeq-0.7.2}/doit.py +0 -0
  32. {geoseeq-0.7.1 → geoseeq-0.7.2}/foo.csv +0 -0
  33. {geoseeq-0.7.1 → geoseeq-0.7.2}/foo.nwk +0 -0
  34. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/__init__.py +0 -0
  35. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/app.py +0 -0
  36. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/blob_constructors.py +0 -0
  37. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/bulk_creators.py +0 -0
  38. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/cli/__init__.py +0 -0
  39. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/cli/constants.py +0 -0
  40. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/cli/copy.py +0 -0
  41. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/cli/detail.py +0 -0
  42. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/cli/download.py +0 -0
  43. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/cli/fastq_utils.py +0 -0
  44. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/cli/find_grn.py +0 -0
  45. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/cli/get_eula.py +0 -0
  46. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/cli/manage.py +0 -0
  47. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/cli/progress_bar.py +0 -0
  48. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/cli/project.py +0 -0
  49. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/cli/raw.py +0 -0
  50. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/cli/run.py +0 -0
  51. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/cli/search.py +0 -0
  52. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/cli/shared_params/__init__.py +0 -0
  53. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/cli/shared_params/common_state.py +0 -0
  54. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/cli/shared_params/config.py +0 -0
  55. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/cli/shared_params/id_handlers.py +0 -0
  56. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/cli/shared_params/obj_getters.py +0 -0
  57. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/cli/shared_params/opts_and_args.py +0 -0
  58. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/cli/upload/__init__.py +0 -0
  59. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/cli/upload/upload_advanced.py +0 -0
  60. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/cli/upload/upload_reads.py +0 -0
  61. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/cli/user.py +0 -0
  62. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/cli/utils.py +0 -0
  63. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/cli/view.py +0 -0
  64. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/constants.py +0 -0
  65. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/contrib/__init__.py +0 -0
  66. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/contrib/ncbi/README.md +0 -0
  67. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/contrib/ncbi/__init__.py +0 -0
  68. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/contrib/ncbi/api.py +0 -0
  69. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/contrib/ncbi/bioproject.py +0 -0
  70. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/contrib/ncbi/cli.py +0 -0
  71. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/contrib/ncbi/setup_logging.py +0 -0
  72. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/dashboard/dashboard.py +0 -0
  73. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/file_system/filesystem_download.py +0 -0
  74. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/file_system/main.py +0 -0
  75. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/file_system_cache.py +0 -0
  76. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/id_constructors/__init__.py +0 -0
  77. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/id_constructors/from_blobs.py +0 -0
  78. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/id_constructors/from_ids.py +0 -0
  79. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/id_constructors/from_names.py +0 -0
  80. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/id_constructors/from_uuids.py +0 -0
  81. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/id_constructors/resolvers.py +0 -0
  82. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/id_constructors/utils.py +0 -0
  83. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/knex.py +0 -0
  84. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/organization.py +0 -0
  85. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/pipeline.py +0 -0
  86. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/plotting/README.md +0 -0
  87. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/plotting/__init__.py +0 -0
  88. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/plotting/constants.py +0 -0
  89. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/plotting/highcharts.py +0 -0
  90. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/plotting/map/__init__.py +0 -0
  91. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/plotting/map/base_layer.py +0 -0
  92. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/plotting/map/map.py +0 -0
  93. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/plotting/map/overlay.py +0 -0
  94. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/plotting/selectable.py +0 -0
  95. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/project.py +0 -0
  96. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/remote_object.py +0 -0
  97. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/result/__init__.py +0 -0
  98. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/result/bioinfo.py +0 -0
  99. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/result/file_chunker.py +0 -0
  100. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/result/file_download.py +0 -0
  101. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/result/file_upload.py +0 -0
  102. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/result/result_file.py +0 -0
  103. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/result/result_folder.py +0 -0
  104. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/result/resumable_download_tracker.py +0 -0
  105. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/result/resumable_upload_tracker.py +0 -0
  106. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/result/smart_objects.py +0 -0
  107. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/result/utils.py +0 -0
  108. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/sample.py +0 -0
  109. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/search.py +0 -0
  110. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/smart_table.py +0 -0
  111. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/smart_tree.py +0 -0
  112. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/upload_download_manager.py +0 -0
  113. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/user.py +0 -0
  114. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/utils.py +0 -0
  115. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/vc/README.md +0 -0
  116. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/vc/__init__.py +0 -0
  117. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/vc/checksum.py +0 -0
  118. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/vc/cli.py +0 -0
  119. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/vc/clone.py +0 -0
  120. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/vc/constants.py +0 -0
  121. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/vc/vc_cache.py +0 -0
  122. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/vc/vc_dir.py +0 -0
  123. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/vc/vc_sample.py +0 -0
  124. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/vc/vc_stub.py +0 -0
  125. {geoseeq-0.7.1 → geoseeq-0.7.2}/geoseeq/work_orders.py +0 -0
  126. {geoseeq-0.7.1 → geoseeq-0.7.2}/large_file +0 -0
  127. {geoseeq-0.7.1 → geoseeq-0.7.2}/plot_server.py +0 -0
  128. {geoseeq-0.7.1 → geoseeq-0.7.2}/setup.py +0 -0
  129. {geoseeq-0.7.1 → geoseeq-0.7.2}/srr7785189.short_read__paired_end.short_read__paired_end__read_1__lane_1.fastq.gz +0 -0
  130. {geoseeq-0.7.1 → geoseeq-0.7.2}/srr7785189.short_read__paired_end.short_read__paired_end__read_1__lane_1.fastq.gz.gs_downloaded +0 -0
  131. {geoseeq-0.7.1 → geoseeq-0.7.2}/srr7785189.short_read__paired_end.short_read__paired_end__read_2__lane_1.fastq.gz +0 -0
  132. {geoseeq-0.7.1 → geoseeq-0.7.2}/srr7785189.short_read__paired_end.short_read__paired_end__read_2__lane_1.fastq.gz.gs_downloaded +0 -0
  133. {geoseeq-0.7.1 → geoseeq-0.7.2}/tests/__init__.py +0 -0
  134. {geoseeq-0.7.1 → geoseeq-0.7.2}/tests/test_api_client.py +0 -0
  135. {geoseeq-0.7.1 → geoseeq-0.7.2}/tests/test_files/files_path.txt +0 -0
  136. {geoseeq-0.7.1 → geoseeq-0.7.2}/tests/test_files/sampleclit.R1.fastq.gz +0 -0
  137. {geoseeq-0.7.1 → geoseeq-0.7.2}/tests/test_files/sampleclit.R2.fastq.gz +0 -0
  138. {geoseeq-0.7.1 → geoseeq-0.7.2}/tests/test_files/single-end.fastq.gz +0 -0
  139. {geoseeq-0.7.1 → geoseeq-0.7.2}/tests/test_files/test_metadata.csv +0 -0
  140. {geoseeq-0.7.1 → geoseeq-0.7.2}/tests/test_files/test_small.R1.fastq.gz +0 -0
  141. {geoseeq-0.7.1 → geoseeq-0.7.2}/tests/test_files/test_small.R2.fastq.gz +0 -0
  142. {geoseeq-0.7.1 → geoseeq-0.7.2}/tests/test_plotting.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: geoseeq
3
- Version: 0.7.1
3
+ Version: 0.7.2
4
4
  Summary: GeoSeeq command line tools and python API
5
5
  Project-URL: Homepage, https://github.com/biotia/geoseeq_api_client
6
6
  Project-URL: Issues, https://github.com/biotia/geoseeq_api_client/issues
@@ -15,6 +15,11 @@ Requires-Dist: click
15
15
  Requires-Dist: pandas
16
16
  Requires-Dist: requests
17
17
  Requires-Dist: tqdm
18
+ Provides-Extra: test
19
+ Requires-Dist: pytest-cov>=4.0; extra == 'test'
20
+ Requires-Dist: pytest-mock>=3.10; extra == 'test'
21
+ Requires-Dist: pytest>=7.0; extra == 'test'
22
+ Requires-Dist: requests-mock>=1.11; extra == 'test'
18
23
  Description-Content-Type: text/markdown
19
24
 
20
25
  # Geoseeq API Client
@@ -55,7 +55,7 @@ def version():
55
55
  Use of this tool implies acceptance of the GeoSeeq End User License Agreement.
56
56
  Run `geoseeq eula show` to view the EULA.
57
57
  """
58
- click.echo('0.7.1') # remember to update pyproject.toml
58
+ click.echo('0.7.2') # remember to update pyproject.toml
59
59
 
60
60
 
61
61
  @main.group('advanced')
@@ -128,9 +128,9 @@ def cli_upload_file(state, cores, threads_per_upload, num_retries, chunk_size_mb
128
128
  )
129
129
  for geoseeq_file_name, file_path in name_pairs:
130
130
  if isfile(file_path):
131
- upload_manager.add_local_file_to_result_folder(result_folder, file_path)
131
+ upload_manager.add_local_file_to_result_folder(result_folder, file_path, geoseeq_file_name=geoseeq_file_name)
132
132
  elif isdir(file_path) and recursive:
133
- upload_manager.add_local_folder_to_result_folder(result_folder, file_path, recursive=recursive, hidden_files=hidden, prefix=file_path)
133
+ upload_manager.add_local_folder_to_result_folder(result_folder, file_path, recursive=recursive, hidden_files=hidden, prefix=file_path, geoseeq_file_name=geoseeq_file_name)
134
134
  elif isdir(file_path) and not recursive:
135
135
  raise click.UsageError('Cannot upload a folder without --recursive')
136
136
  click.echo(upload_manager.get_preview_string(), err=True)
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "geoseeq"
7
- version = "0.7.1"
7
+ version = "0.7.2"
8
8
  authors = [
9
9
  { name="David C. Danko", email="dcdanko@biotia.io" },
10
10
  ]
@@ -24,9 +24,22 @@ dependencies = [
24
24
  "tqdm",
25
25
  ]
26
26
 
27
+ [project.optional-dependencies]
28
+ test = [
29
+ "pytest>=7.0",
30
+ "pytest-cov>=4.0",
31
+ "pytest-mock>=3.10",
32
+ "requests-mock>=1.11",
33
+ ]
34
+
27
35
  [project.urls]
28
36
  Homepage = "https://github.com/biotia/geoseeq_api_client"
29
37
  Issues = "https://github.com/biotia/geoseeq_api_client/issues"
30
38
 
31
39
  [project.scripts]
32
40
  geoseeq = "geoseeq.cli:main"
41
+
42
+ [tool.pytest.ini_options]
43
+ testpaths = ["tests"]
44
+ python_files = ["test_*.py"]
45
+ addopts = "-v --cov=geoseeq"
@@ -0,0 +1,55 @@
1
+ import os
2
+ import pytest
3
+ from click.testing import CliRunner
4
+ from geoseeq.knex import Knex
5
+ from geoseeq.cli import main
6
+
7
+ # Test organization and user configuration
8
+ TEST_ORG_NAME = "API Client Test Organization"
9
+ TEST_USER_EMAIL = "api-client-test@biotia.io"
10
+ TEST_USER_PASSWORD = os.getenv("GEOSEEQ_TEST_PASSWORD", "test-password-please-change")
11
+
12
+ @pytest.fixture(scope="session")
13
+ def test_knex():
14
+ """Create a Knex instance for testing."""
15
+ knex = Knex()
16
+ # Login with test user
17
+ knex.login(TEST_USER_EMAIL, TEST_USER_PASSWORD)
18
+ return knex
19
+
20
+ @pytest.fixture(scope="session")
21
+ def test_org(test_knex):
22
+ """Get or create the test organization."""
23
+ org = test_knex.get_org(TEST_ORG_NAME)
24
+ if not org:
25
+ org = test_knex.create_org(TEST_ORG_NAME)
26
+ return org
27
+
28
+ @pytest.fixture(scope="function")
29
+ def test_project(test_org):
30
+ """Create a temporary project for testing."""
31
+ project = test_org.create_project("test-project")
32
+ yield project
33
+ # Cleanup after test
34
+ project.delete()
35
+
36
+ @pytest.fixture(scope="function")
37
+ def test_sample(test_project):
38
+ """Create a temporary sample for testing."""
39
+ sample = test_project.create_sample("test-sample")
40
+ yield sample
41
+ # Cleanup after test
42
+ sample.delete()
43
+
44
+ @pytest.fixture(scope="function")
45
+ def test_read_folder(test_sample):
46
+ """Create a temporary read folder for testing."""
47
+ read_folder = test_sample.create_read_folder("test-reads")
48
+ yield read_folder
49
+ # Cleanup after test
50
+ read_folder.delete()
51
+
52
+ @pytest.fixture
53
+ def runner():
54
+ """Create a CLI runner for testing."""
55
+ return CliRunner()
@@ -0,0 +1,104 @@
1
+ import os
2
+ import tempfile
3
+ import unittest
4
+ from pathlib import Path
5
+ from geoseeq.knex import Knex
6
+ from geoseeq.organization import Organization
7
+ from geoseeq.upload_download_manager import GeoSeeqDownloadManager
8
+ from time import sleep
9
+
10
+ class TestDownload(unittest.TestCase):
11
+ @classmethod
12
+ def setUpClass(cls):
13
+ # Test configuration from environment variables
14
+ cls.test_org_name = os.getenv("GEOSEEQ_TEST_ORG", "API Client Test Organization")
15
+ cls.test_api_token = os.getenv("GEOSEEQ_TEST_API_TOKEN")
16
+ if not cls.test_api_token:
17
+ raise ValueError("GEOSEEQ_TEST_API_TOKEN environment variable must be set")
18
+
19
+ def setUp(self):
20
+ # Set up test environment
21
+ self.knex = Knex()
22
+ self.knex.add_api_token(self.test_api_token)
23
+ self.org = Organization(self.knex, self.test_org_name)
24
+ self.org.get() # Fetch the existing organization
25
+ self.project = self.org.project("test-download-project")
26
+ self.sample = self.project.sample("test-single-sample")
27
+ self.read_folder = self.sample.result_folder("short_read::single_end")
28
+ self.read_folder.idem() # Ensure the folder exists
29
+ self.multi_sample = self.project.sample("test-multi-sample")
30
+ self.multi_sample_folder = self.multi_sample.result_folder("short_read::single_end")
31
+ self.multi_sample_folder.idem() # Ensure the folder exists
32
+ self.tmp_dir = tempfile.TemporaryDirectory()
33
+ self.tmp_path = Path(self.tmp_dir.name)
34
+
35
+ def tearDown(self):
36
+ self.tmp_dir.cleanup()
37
+
38
+ def create_test_fastq_file(self, name, content="ATCG"):
39
+ """Create a test FASTQ file with the given content."""
40
+ filepath = self.tmp_path / name
41
+ with open(filepath, 'w') as f:
42
+ f.write(f"@test\n{content}\n+\n{'I' * len(content)}\n")
43
+ return filepath
44
+
45
+ def test_programmatic_single_file_download(self):
46
+ """Test downloading a single file using the API directly."""
47
+ # Create and upload test file
48
+ test_file = self.create_test_fastq_file("test.fastq", "ATCG")
49
+ result_file = self.read_folder.result_file("R1")
50
+ result_file.idem() # Ensure the file exists
51
+ result_file.upload_file(test_file)
52
+ sleep(5)
53
+
54
+ # Download the file
55
+ download_path = self.tmp_path / "downloaded.fastq"
56
+ result_file.download(str(download_path))
57
+
58
+ # Verify download
59
+ self.assertTrue(download_path.exists())
60
+
61
+ # Compare contents
62
+ with open(test_file) as f1, open(download_path) as f2:
63
+ self.assertEqual(f1.read(), f2.read())
64
+
65
+ def test_programmatic_download_manager(self):
66
+ """Test downloading multiple files using the download manager."""
67
+ # Create and upload test files
68
+ files = [
69
+ self.create_test_fastq_file(f"test_{i}.fastq", f"ATCG{i}")
70
+ for i in range(3)
71
+ ]
72
+
73
+ result_files = []
74
+ for i, file_path in enumerate(files):
75
+ result_file = self.multi_sample_folder.result_file(f"R{i+1}")
76
+ result_file.idem() # Ensure the file exists
77
+ result_file.upload_file(file_path)
78
+ result_files.append(result_file)
79
+
80
+ sleep(5)
81
+
82
+ # Set up download manager
83
+ download_manager = GeoSeeqDownloadManager(n_parallel_downloads=2)
84
+
85
+ # Add files to download manager
86
+ download_paths = []
87
+ for i, result_file in enumerate(result_files):
88
+ download_path = self.tmp_path / f"downloaded_{i}.fastq"
89
+ download_manager.add_download(result_file, str(download_path))
90
+ download_paths.append(download_path)
91
+
92
+ # Download files
93
+ download_manager.download_files()
94
+
95
+ # Verify downloads
96
+ for i, (original_path, download_path) in enumerate(zip(files, download_paths)):
97
+ self.assertTrue(download_path.exists())
98
+
99
+ # Compare contents
100
+ with open(original_path) as f1, open(download_path) as f2:
101
+ self.assertEqual(f1.read(), f2.read())
102
+
103
+ if __name__ == '__main__':
104
+ unittest.main()
@@ -0,0 +1,124 @@
1
+ import os
2
+ import tempfile
3
+ import unittest
4
+ from pathlib import Path
5
+ from click.testing import CliRunner
6
+ from geoseeq.knex import Knex
7
+ from geoseeq.cli import main
8
+ from geoseeq.organization import Organization
9
+
10
+ class TestDownloadCLI(unittest.TestCase):
11
+ @classmethod
12
+ def setUpClass(cls):
13
+ # Test configuration from environment variables
14
+ cls.test_org_name = os.getenv("GEOSEEQ_TEST_ORG", "API Client Test Organization")
15
+ cls.test_api_token = os.getenv("GEOSEEQ_TEST_API_TOKEN")
16
+ if not cls.test_api_token:
17
+ raise ValueError("GEOSEEQ_TEST_API_TOKEN environment variable must be set")
18
+
19
+ def setUp(self):
20
+ # Set up test environment
21
+ self.knex = Knex()
22
+ self.knex.add_api_token(self.test_api_token)
23
+ self.org = Organization(self.knex, self.test_org_name)
24
+ self.org.get() # Fetch the existing organization
25
+ self.project = self.org.project("test-project")
26
+ self.tmp_dir = tempfile.TemporaryDirectory()
27
+ self.tmp_path = Path(self.tmp_dir.name)
28
+
29
+ def tearDown(self):
30
+ self.tmp_dir.cleanup()
31
+
32
+ def create_test_fastq_file(self, name, content="ATCG"):
33
+ """Create a test FASTQ file with the given content."""
34
+ filepath = self.tmp_path / name
35
+ with open(filepath, 'w') as f:
36
+ f.write(f"@test\n{content}\n+\n{'I' * len(content)}\n")
37
+ return filepath
38
+
39
+ def test_cli_single_end_download(self):
40
+ """Test downloading single-end FASTQ files using the CLI."""
41
+ # Create and upload test files
42
+ files = [
43
+ self.create_test_fastq_file(f"sample_{i}.fastq", f"ATCG{i}")
44
+ for i in range(3)
45
+ ]
46
+
47
+ # Upload files
48
+ for i, file_path in enumerate(files):
49
+ sample = self.project.sample(f"sample_{i}")
50
+ read_folder = sample.result_folder("short_read::single_end")
51
+ read_folder.upload_file(file_path, "R1")
52
+
53
+ # Create download directory
54
+ download_dir = self.tmp_path / "downloads"
55
+ download_dir.mkdir()
56
+
57
+ # Run CLI command
58
+ runner = CliRunner()
59
+ result = runner.invoke(
60
+ main,
61
+ ['download',
62
+ 'reads',
63
+ '--yes',
64
+ str(self.project.uuid),
65
+ str(download_dir)]
66
+ )
67
+
68
+ self.assertEqual(result.exit_code, 0)
69
+
70
+ # Verify downloads
71
+ for i in range(3):
72
+ downloaded_file = download_dir / f"sample_{i}" / "short_read::single_end" / "R1.fastq"
73
+ self.assertTrue(downloaded_file.exists())
74
+
75
+ # Compare contents
76
+ with open(files[i]) as f1, open(downloaded_file) as f2:
77
+ self.assertEqual(f1.read(), f2.read())
78
+
79
+ def test_cli_paired_end_download(self):
80
+ """Test downloading paired-end FASTQ files using the CLI."""
81
+ # Create and upload test files
82
+ for i in range(3):
83
+ r1_file = self.create_test_fastq_file(f"sample_{i}_R1.fastq", f"ATCG{i}")
84
+ r2_file = self.create_test_fastq_file(f"sample_{i}_R2.fastq", f"GCTA{i}")
85
+
86
+ sample = self.project.sample(f"sample_{i}")
87
+ read_folder = sample.result_folder("short_read::paired_end")
88
+ read_folder.upload_file(r1_file, "R1")
89
+ read_folder.upload_file(r2_file, "R2")
90
+
91
+ # Create download directory
92
+ download_dir = self.tmp_path / "downloads"
93
+ download_dir.mkdir()
94
+
95
+ # Run CLI command
96
+ runner = CliRunner()
97
+ result = runner.invoke(
98
+ main,
99
+ ['download',
100
+ 'reads',
101
+ '--yes',
102
+ str(self.project.uuid),
103
+ str(download_dir)]
104
+ )
105
+
106
+ self.assertEqual(result.exit_code, 0)
107
+
108
+ # Verify downloads
109
+ for i in range(3):
110
+ sample_dir = download_dir / f"sample_{i}" / "short_read::paired_end"
111
+ r1_downloaded = sample_dir / "R1.fastq"
112
+ r2_downloaded = sample_dir / "R2.fastq"
113
+
114
+ self.assertTrue(r1_downloaded.exists())
115
+ self.assertTrue(r2_downloaded.exists())
116
+
117
+ # Compare contents
118
+ with open(Path(self.tmp_path) / f"sample_{i}_R1.fastq") as f1, open(r1_downloaded) as f2:
119
+ self.assertEqual(f1.read(), f2.read())
120
+ with open(Path(self.tmp_path) / f"sample_{i}_R2.fastq") as f1, open(r2_downloaded) as f2:
121
+ self.assertEqual(f1.read(), f2.read())
122
+
123
+ if __name__ == '__main__':
124
+ unittest.main()
@@ -0,0 +1,76 @@
1
+ import os
2
+ import tempfile
3
+ import unittest
4
+ from pathlib import Path
5
+ from geoseeq.knex import Knex
6
+ from geoseeq.organization import Organization
7
+ from geoseeq.upload_download_manager import GeoSeeqUploadManager
8
+
9
+ class TestUpload(unittest.TestCase):
10
+ @classmethod
11
+ def setUpClass(cls):
12
+ # Test configuration from environment variables
13
+ cls.test_org_name = os.getenv("GEOSEEQ_TEST_ORG", "API Client Test Organization")
14
+ cls.test_api_token = os.getenv("GEOSEEQ_TEST_API_TOKEN")
15
+ if not cls.test_api_token:
16
+ raise ValueError("GEOSEEQ_TEST_API_TOKEN environment variable must be set")
17
+
18
+ def setUp(self):
19
+ # Set up test environment
20
+ self.knex = Knex()
21
+ self.knex.add_api_token(self.test_api_token)
22
+ self.org = Organization(self.knex, self.test_org_name)
23
+ self.org.get() # Fetch the existing organization
24
+ self.project = self.org.project("test-project")
25
+ self.sample = self.project.sample("test-sample")
26
+ self.read_folder = self.sample.result_folder("short_read::single_end")
27
+ self.tmp_dir = tempfile.TemporaryDirectory()
28
+ self.tmp_path = Path(self.tmp_dir.name)
29
+
30
+ def tearDown(self):
31
+ self.tmp_dir.cleanup()
32
+
33
+ def create_test_fastq_file(self, name, content="ATCG"):
34
+ """Create a test FASTQ file with the given content."""
35
+ filepath = self.tmp_path / name
36
+ with open(filepath, 'w') as f:
37
+ f.write(f"@test\n{content}\n+\n{'I' * len(content)}\n")
38
+ return filepath
39
+
40
+ def test_programmatic_single_file_upload(self):
41
+ """Test uploading a single file using the API directly."""
42
+ # Create test file
43
+ test_file = self.create_test_fastq_file("test.fastq")
44
+
45
+ # Upload using the API
46
+ result_file = self.read_folder.upload_file(test_file, "R1")
47
+
48
+ # Verify upload
49
+ self.assertTrue(result_file.exists())
50
+
51
+ def test_programmatic_upload_manager(self):
52
+ """Test uploading multiple files using the upload manager."""
53
+ # Create test files
54
+ files = [
55
+ self.create_test_fastq_file(f"test_{i}.fastq", f"ATCG{i}")
56
+ for i in range(3)
57
+ ]
58
+
59
+ # Set up upload manager
60
+ upload_manager = GeoSeeqUploadManager(n_parallel_uploads=2)
61
+
62
+ # Add files to upload manager
63
+ for i, file_path in enumerate(files):
64
+ result_file = self.read_folder.result_file(f"R{i+1}")
65
+ upload_manager.add_result_file(result_file, file_path)
66
+
67
+ # Upload files
68
+ upload_manager.upload_files()
69
+
70
+ # Verify uploads
71
+ for i in range(3):
72
+ result_file = self.read_folder.result_file(f"R{i+1}")
73
+ self.assertTrue(result_file.exists())
74
+
75
+ if __name__ == '__main__':
76
+ unittest.main()
@@ -0,0 +1,112 @@
1
+ import os
2
+ import tempfile
3
+ import unittest
4
+ from pathlib import Path
5
+ from click.testing import CliRunner
6
+ from geoseeq.knex import Knex
7
+ from geoseeq.cli import main
8
+ from geoseeq.organization import Organization
9
+
10
+ class TestUploadCLI(unittest.TestCase):
11
+ @classmethod
12
+ def setUpClass(cls):
13
+ # Test configuration from environment variables
14
+ cls.test_org_name = os.getenv("GEOSEEQ_TEST_ORG", "API Client Test Organization")
15
+ cls.test_api_token = os.getenv("GEOSEEQ_TEST_API_TOKEN")
16
+ if not cls.test_api_token:
17
+ raise ValueError("GEOSEEQ_TEST_API_TOKEN environment variable must be set")
18
+
19
+ def setUp(self):
20
+ # Set up test environment
21
+ self.knex = Knex()
22
+ self.knex.add_api_token(self.test_api_token)
23
+ self.org = Organization(self.knex, self.test_org_name)
24
+ self.org.get() # Fetch the existing organization
25
+ self.project = self.org.project("test-project")
26
+ self.tmp_dir = tempfile.TemporaryDirectory()
27
+ self.tmp_path = Path(self.tmp_dir.name)
28
+
29
+ def tearDown(self):
30
+ self.tmp_dir.cleanup()
31
+
32
+ def create_test_fastq_file(self, name, content="ATCG"):
33
+ """Create a test FASTQ file with the given content."""
34
+ filepath = self.tmp_path / name
35
+ with open(filepath, 'w') as f:
36
+ f.write(f"@test\n{content}\n+\n{'I' * len(content)}\n")
37
+ return filepath
38
+
39
+ def test_cli_single_end_upload(self):
40
+ """Test uploading single-end FASTQ files using the CLI."""
41
+ # Create test files
42
+ files = [
43
+ self.create_test_fastq_file(f"sample_{i}.fastq", f"ATCG{i}")
44
+ for i in range(3)
45
+ ]
46
+
47
+ # Create a file list
48
+ file_list = self.tmp_path / "file_list.txt"
49
+ with open(file_list, 'w') as f:
50
+ for file in files:
51
+ f.write(f"{file}\n")
52
+
53
+ # Run CLI command
54
+ runner = CliRunner()
55
+ result = runner.invoke(
56
+ main,
57
+ ['upload', 'reads',
58
+ '--regex', r'(?P<sample_name>sample_\d+)\.fastq',
59
+ '--module-name', 'short_read::single_end',
60
+ '--yes',
61
+ str(self.project.uuid),
62
+ str(file_list)]
63
+ )
64
+
65
+ self.assertEqual(result.exit_code, 0)
66
+
67
+ # Verify uploads
68
+ for i in range(3):
69
+ sample = self.project.sample(f"sample_{i}")
70
+ read_folder = sample.result_folder("short_read::single_end")
71
+ result_file = read_folder.result_file("R1")
72
+ self.assertTrue(result_file.exists())
73
+
74
+ def test_cli_paired_end_upload(self):
75
+ """Test uploading paired-end FASTQ files using the CLI."""
76
+ # Create test files
77
+ for i in range(3):
78
+ self.create_test_fastq_file(f"sample_{i}_R1.fastq", f"ATCG{i}")
79
+ self.create_test_fastq_file(f"sample_{i}_R2.fastq", f"GCTA{i}")
80
+
81
+ # Create a file list
82
+ file_list = self.tmp_path / "file_list.txt"
83
+ with open(file_list, 'w') as f:
84
+ for i in range(3):
85
+ f.write(f"{self.tmp_path}/sample_{i}_R1.fastq\n")
86
+ f.write(f"{self.tmp_path}/sample_{i}_R2.fastq\n")
87
+
88
+ # Run CLI command
89
+ runner = CliRunner()
90
+ result = runner.invoke(
91
+ main,
92
+ ['upload', 'reads',
93
+ '--regex', r'(?P<sample_name>sample_\d+)_R(?P<pair_num>[12])\.fastq',
94
+ '--module-name', 'short_read::paired_end',
95
+ '--yes',
96
+ str(self.project.uuid),
97
+ str(file_list)]
98
+ )
99
+
100
+ self.assertEqual(result.exit_code, 0)
101
+
102
+ # Verify uploads
103
+ for i in range(3):
104
+ sample = self.project.sample(f"sample_{i}")
105
+ read_folder = sample.result_folder("short_read::paired_end")
106
+ r1_file = read_folder.result_file("R1")
107
+ r2_file = read_folder.result_file("R2")
108
+ self.assertTrue(r1_file.exists())
109
+ self.assertTrue(r2_file.exists())
110
+
111
+ if __name__ == '__main__':
112
+ unittest.main()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes