arctrl 3.0.0a3__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.
- arctrl/__init__.py +18 -0
- arctrl/py/CWL/__init__.py +0 -0
- arctrl/py/CWL/cwltypes.py +150 -0
- arctrl/py/CWL/decode.py +973 -0
- arctrl/py/CWL/encode.py +1 -0
- arctrl/py/CWL/inputs.py +88 -0
- arctrl/py/CWL/outputs.py +85 -0
- arctrl/py/CWL/requirements.py +77 -0
- arctrl/py/CWL/tool_description.py +103 -0
- arctrl/py/CWL/workflow_description.py +104 -0
- arctrl/py/CWL/workflow_steps.py +113 -0
- arctrl/py/Contract/__init__.py +0 -0
- arctrl/py/Contract/arc.py +60 -0
- arctrl/py/Contract/arc_assay.py +125 -0
- arctrl/py/Contract/arc_investigation.py +88 -0
- arctrl/py/Contract/arc_run.py +125 -0
- arctrl/py/Contract/arc_study.py +126 -0
- arctrl/py/Contract/arc_workflow.py +125 -0
- arctrl/py/Contract/contract.py +153 -0
- arctrl/py/Contract/datamap.py +372 -0
- arctrl/py/Contract/git.py +118 -0
- arctrl/py/Contract/validation_packages_config.py +107 -0
- arctrl/py/ContractIO/__init__.py +0 -0
- arctrl/py/ContractIO/contract_io.py +344 -0
- arctrl/py/ContractIO/file_system_helper.py +264 -0
- arctrl/py/Core/Helper/__init__.py +0 -0
- arctrl/py/Core/Helper/collections_.py +438 -0
- arctrl/py/Core/Helper/date_time.py +26 -0
- arctrl/py/Core/Helper/hash_codes.py +60 -0
- arctrl/py/Core/Helper/identifier.py +248 -0
- arctrl/py/Core/Helper/orcid.py +42 -0
- arctrl/py/Core/Helper/printer.py +13 -0
- arctrl/py/Core/Helper/regex.py +554 -0
- arctrl/py/Core/Helper/sem_ver.py +71 -0
- arctrl/py/Core/Helper/url.py +148 -0
- arctrl/py/Core/Process/__init__.py +0 -0
- arctrl/py/Core/Process/column_index.py +280 -0
- arctrl/py/Core/Process/component.py +200 -0
- arctrl/py/Core/Process/factor.py +151 -0
- arctrl/py/Core/Process/factor_value.py +182 -0
- arctrl/py/Core/Process/material.py +74 -0
- arctrl/py/Core/Process/material_attribute.py +95 -0
- arctrl/py/Core/Process/material_attribute_value.py +184 -0
- arctrl/py/Core/Process/material_type.py +45 -0
- arctrl/py/Core/Process/process.py +477 -0
- arctrl/py/Core/Process/process_input.py +265 -0
- arctrl/py/Core/Process/process_output.py +235 -0
- arctrl/py/Core/Process/process_parameter_value.py +200 -0
- arctrl/py/Core/Process/process_sequence.py +435 -0
- arctrl/py/Core/Process/protocol.py +175 -0
- arctrl/py/Core/Process/protocol_parameter.py +98 -0
- arctrl/py/Core/Process/sample.py +82 -0
- arctrl/py/Core/Process/source.py +62 -0
- arctrl/py/Core/Table/__init__.py +0 -0
- arctrl/py/Core/Table/arc_table.py +1264 -0
- arctrl/py/Core/Table/arc_table_aux.py +575 -0
- arctrl/py/Core/Table/arc_tables.py +591 -0
- arctrl/py/Core/Table/composite_cell.py +319 -0
- arctrl/py/Core/Table/composite_column.py +73 -0
- arctrl/py/Core/Table/composite_header.py +739 -0
- arctrl/py/Core/__init__.py +0 -0
- arctrl/py/Core/arc_types.py +5064 -0
- arctrl/py/Core/comment.py +128 -0
- arctrl/py/Core/comment_list.py +127 -0
- arctrl/py/Core/conversion.py +1313 -0
- arctrl/py/Core/data.py +245 -0
- arctrl/py/Core/data_context.py +157 -0
- arctrl/py/Core/data_file.py +112 -0
- arctrl/py/Core/data_map.py +225 -0
- arctrl/py/Core/identifier_setters.py +31 -0
- arctrl/py/Core/iproperty_value.py +36 -0
- arctrl/py/Core/ontology_annotation.py +299 -0
- arctrl/py/Core/ontology_source_reference.py +114 -0
- arctrl/py/Core/person.py +259 -0
- arctrl/py/Core/publication.py +161 -0
- arctrl/py/Core/template.py +231 -0
- arctrl/py/Core/templates.py +148 -0
- arctrl/py/Core/uri.py +11 -0
- arctrl/py/Core/value.py +188 -0
- arctrl/py/FileSystem/__init__.py +0 -0
- arctrl/py/FileSystem/commit.py +21 -0
- arctrl/py/FileSystem/default_gitattributes.py +5 -0
- arctrl/py/FileSystem/default_gitignore.py +5 -0
- arctrl/py/FileSystem/file_system.py +58 -0
- arctrl/py/FileSystem/file_system_tree.py +426 -0
- arctrl/py/FileSystem/path.py +64 -0
- arctrl/py/Json/DataMap/__init__.py +0 -0
- arctrl/py/Json/DataMap/data_context.py +101 -0
- arctrl/py/Json/DataMap/data_map.py +53 -0
- arctrl/py/Json/Process/__init__.py +0 -0
- arctrl/py/Json/Process/assay_materials.py +46 -0
- arctrl/py/Json/Process/component.py +79 -0
- arctrl/py/Json/Process/factor.py +107 -0
- arctrl/py/Json/Process/factor_value.py +101 -0
- arctrl/py/Json/Process/material.py +226 -0
- arctrl/py/Json/Process/material_attribute.py +79 -0
- arctrl/py/Json/Process/material_attribute_value.py +101 -0
- arctrl/py/Json/Process/material_type.py +53 -0
- arctrl/py/Json/Process/process.py +296 -0
- arctrl/py/Json/Process/process_input.py +83 -0
- arctrl/py/Json/Process/process_output.py +67 -0
- arctrl/py/Json/Process/process_parameter_value.py +81 -0
- arctrl/py/Json/Process/protocol.py +354 -0
- arctrl/py/Json/Process/protocol_parameter.py +79 -0
- arctrl/py/Json/Process/sample.py +277 -0
- arctrl/py/Json/Process/source.py +214 -0
- arctrl/py/Json/Process/study_materials.py +52 -0
- arctrl/py/Json/Process/value.py +56 -0
- arctrl/py/Json/ROCrate/__init__.py +0 -0
- arctrl/py/Json/ROCrate/ldcontext.py +133 -0
- arctrl/py/Json/ROCrate/ldgraph.py +111 -0
- arctrl/py/Json/ROCrate/ldnode.py +290 -0
- arctrl/py/Json/ROCrate/ldref.py +44 -0
- arctrl/py/Json/ROCrate/ldvalue.py +102 -0
- arctrl/py/Json/Table/__init__.py +0 -0
- arctrl/py/Json/Table/arc_table.py +393 -0
- arctrl/py/Json/Table/cell_table.py +83 -0
- arctrl/py/Json/Table/composite_cell.py +136 -0
- arctrl/py/Json/Table/composite_header.py +67 -0
- arctrl/py/Json/Table/iotype.py +24 -0
- arctrl/py/Json/Table/oatable.py +82 -0
- arctrl/py/Json/Table/templates.py +281 -0
- arctrl/py/Json/__init__.py +0 -0
- arctrl/py/Json/assay.py +600 -0
- arctrl/py/Json/comment.py +206 -0
- arctrl/py/Json/context/rocrate/__init__.py +0 -0
- arctrl/py/Json/context/rocrate/isa_assay_context.py +101 -0
- arctrl/py/Json/context/rocrate/isa_comment_context.py +60 -0
- arctrl/py/Json/context/rocrate/isa_component_context.py +77 -0
- arctrl/py/Json/context/rocrate/isa_data_context.py +74 -0
- arctrl/py/Json/context/rocrate/isa_factor_context.py +74 -0
- arctrl/py/Json/context/rocrate/isa_factor_value_context.py +84 -0
- arctrl/py/Json/context/rocrate/isa_investigation_context.py +110 -0
- arctrl/py/Json/context/rocrate/isa_material_attribute_context.py +64 -0
- arctrl/py/Json/context/rocrate/isa_material_attribute_value_context.py +80 -0
- arctrl/py/Json/context/rocrate/isa_material_context.py +71 -0
- arctrl/py/Json/context/rocrate/isa_ontology_annotation_context.py +68 -0
- arctrl/py/Json/context/rocrate/isa_ontology_source_reference_context.py +75 -0
- arctrl/py/Json/context/rocrate/isa_organization_context.py +55 -0
- arctrl/py/Json/context/rocrate/isa_person_context.py +131 -0
- arctrl/py/Json/context/rocrate/isa_process_context.py +94 -0
- arctrl/py/Json/context/rocrate/isa_process_parameter_value_context.py +80 -0
- arctrl/py/Json/context/rocrate/isa_protocol_context.py +97 -0
- arctrl/py/Json/context/rocrate/isa_protocol_parameter_context.py +64 -0
- arctrl/py/Json/context/rocrate/isa_publication_context.py +78 -0
- arctrl/py/Json/context/rocrate/isa_sample_context.py +65 -0
- arctrl/py/Json/context/rocrate/isa_source_context.py +66 -0
- arctrl/py/Json/context/rocrate/isa_study_context.py +125 -0
- arctrl/py/Json/context/rocrate/property_value_context.py +73 -0
- arctrl/py/Json/context/rocrate/rocrate_context.py +81 -0
- arctrl/py/Json/converter_options.py +23 -0
- arctrl/py/Json/data.py +356 -0
- arctrl/py/Json/data_file.py +63 -0
- arctrl/py/Json/decode.py +155 -0
- arctrl/py/Json/encode.py +92 -0
- arctrl/py/Json/idtable.py +44 -0
- arctrl/py/Json/investigation.py +695 -0
- arctrl/py/Json/ontology_annotation.py +404 -0
- arctrl/py/Json/ontology_source_reference.py +255 -0
- arctrl/py/Json/person.py +658 -0
- arctrl/py/Json/property_value.py +359 -0
- arctrl/py/Json/publication.py +279 -0
- arctrl/py/Json/string_table.py +76 -0
- arctrl/py/Json/study.py +793 -0
- arctrl/py/JsonIO/DataMap/__init__.py +0 -0
- arctrl/py/JsonIO/DataMap/data_map.py +53 -0
- arctrl/py/JsonIO/Process/__init__.py +0 -0
- arctrl/py/JsonIO/Process/component.py +60 -0
- arctrl/py/JsonIO/Process/factor.py +36 -0
- arctrl/py/JsonIO/Process/factor_value.py +38 -0
- arctrl/py/JsonIO/Process/material.py +60 -0
- arctrl/py/JsonIO/Process/material_attribute.py +38 -0
- arctrl/py/JsonIO/Process/material_attribute_value.py +60 -0
- arctrl/py/JsonIO/Process/material_type.py +36 -0
- arctrl/py/JsonIO/Process/process.py +60 -0
- arctrl/py/JsonIO/Process/process_input.py +38 -0
- arctrl/py/JsonIO/Process/process_output.py +60 -0
- arctrl/py/JsonIO/Process/process_parameter_value.py +60 -0
- arctrl/py/JsonIO/Process/process_sequence.py +71 -0
- arctrl/py/JsonIO/Process/protocol.py +60 -0
- arctrl/py/JsonIO/Process/protocol_parameter.py +36 -0
- arctrl/py/JsonIO/Process/sample.py +60 -0
- arctrl/py/JsonIO/Process/source.py +60 -0
- arctrl/py/JsonIO/Process/study_materials.py +52 -0
- arctrl/py/JsonIO/Process/value.py +32 -0
- arctrl/py/JsonIO/Table/__init__.py +0 -0
- arctrl/py/JsonIO/Table/arc_table.py +121 -0
- arctrl/py/JsonIO/Table/composite_cell.py +36 -0
- arctrl/py/JsonIO/Table/composite_header.py +36 -0
- arctrl/py/JsonIO/Table/compression.py +85 -0
- arctrl/py/JsonIO/Table/iotype.py +36 -0
- arctrl/py/JsonIO/Table/templates.py +113 -0
- arctrl/py/JsonIO/__init__.py +0 -0
- arctrl/py/JsonIO/assay.py +113 -0
- arctrl/py/JsonIO/comment.py +80 -0
- arctrl/py/JsonIO/data.py +60 -0
- arctrl/py/JsonIO/data_file.py +58 -0
- arctrl/py/JsonIO/decode.py +9 -0
- arctrl/py/JsonIO/encode.py +1 -0
- arctrl/py/JsonIO/investigation.py +113 -0
- arctrl/py/JsonIO/ldobject.py +106 -0
- arctrl/py/JsonIO/ontology_annotation.py +80 -0
- arctrl/py/JsonIO/ontology_source_reference.py +80 -0
- arctrl/py/JsonIO/person.py +82 -0
- arctrl/py/JsonIO/publication.py +82 -0
- arctrl/py/JsonIO/study.py +114 -0
- arctrl/py/ROCrate/Generic/__init__.py +0 -0
- arctrl/py/ROCrate/Generic/comment.py +131 -0
- arctrl/py/ROCrate/Generic/dataset.py +817 -0
- arctrl/py/ROCrate/Generic/defined_term.py +131 -0
- arctrl/py/ROCrate/Generic/file.py +237 -0
- arctrl/py/ROCrate/Generic/lab_process.py +324 -0
- arctrl/py/ROCrate/Generic/lab_protocol.py +338 -0
- arctrl/py/ROCrate/Generic/organization.py +83 -0
- arctrl/py/ROCrate/Generic/person.py +484 -0
- arctrl/py/ROCrate/Generic/postal_address.py +195 -0
- arctrl/py/ROCrate/Generic/property_value.py +696 -0
- arctrl/py/ROCrate/Generic/sample.py +202 -0
- arctrl/py/ROCrate/Generic/scholarly_article.py +229 -0
- arctrl/py/ROCrate/ISAProfile/__init__.py +0 -0
- arctrl/py/ROCrate/ISAProfile/assay.py +70 -0
- arctrl/py/ROCrate/ISAProfile/data.py +65 -0
- arctrl/py/ROCrate/ISAProfile/dataset.py +24 -0
- arctrl/py/ROCrate/ISAProfile/investigation.py +73 -0
- arctrl/py/ROCrate/ISAProfile/lab_process.py +162 -0
- arctrl/py/ROCrate/ISAProfile/lab_protocol.py +37 -0
- arctrl/py/ROCrate/ISAProfile/person.py +72 -0
- arctrl/py/ROCrate/ISAProfile/property_value.py +98 -0
- arctrl/py/ROCrate/ISAProfile/sample.py +64 -0
- arctrl/py/ROCrate/ISAProfile/scholarly_article.py +98 -0
- arctrl/py/ROCrate/ISAProfile/study.py +74 -0
- arctrl/py/ROCrate/__init__.py +0 -0
- arctrl/py/ROCrate/arc_rocrate_metadata.py +39 -0
- arctrl/py/ROCrate/dyn_obj_extensions.py +1 -0
- arctrl/py/ROCrate/helper.py +8 -0
- arctrl/py/ROCrate/ldcontext.py +362 -0
- arctrl/py/ROCrate/ldobject.py +1247 -0
- arctrl/py/ROCrate/rocrate_context.py +51 -0
- arctrl/py/Spreadsheet/AnnotationTable/__init__.py +0 -0
- arctrl/py/Spreadsheet/AnnotationTable/arc_table.py +193 -0
- arctrl/py/Spreadsheet/AnnotationTable/composite_cell.py +78 -0
- arctrl/py/Spreadsheet/AnnotationTable/composite_column.py +210 -0
- arctrl/py/Spreadsheet/AnnotationTable/composite_header.py +623 -0
- arctrl/py/Spreadsheet/DataMapTable/__init__.py +0 -0
- arctrl/py/Spreadsheet/DataMapTable/data_map_column.py +114 -0
- arctrl/py/Spreadsheet/DataMapTable/data_map_header.py +618 -0
- arctrl/py/Spreadsheet/DataMapTable/data_map_table.py +119 -0
- arctrl/py/Spreadsheet/Metadata/__init__.py +0 -0
- arctrl/py/Spreadsheet/Metadata/assays.py +125 -0
- arctrl/py/Spreadsheet/Metadata/comment.py +77 -0
- arctrl/py/Spreadsheet/Metadata/contacts.py +134 -0
- arctrl/py/Spreadsheet/Metadata/conversions.py +190 -0
- arctrl/py/Spreadsheet/Metadata/design_descriptors.py +34 -0
- arctrl/py/Spreadsheet/Metadata/factors.py +107 -0
- arctrl/py/Spreadsheet/Metadata/ontology_annotation.py +88 -0
- arctrl/py/Spreadsheet/Metadata/ontology_source_reference.py +96 -0
- arctrl/py/Spreadsheet/Metadata/protocols.py +146 -0
- arctrl/py/Spreadsheet/Metadata/publication.py +122 -0
- arctrl/py/Spreadsheet/Metadata/run.py +122 -0
- arctrl/py/Spreadsheet/Metadata/sparse_table.py +508 -0
- arctrl/py/Spreadsheet/Metadata/study.py +312 -0
- arctrl/py/Spreadsheet/Metadata/workflow.py +151 -0
- arctrl/py/Spreadsheet/__init__.py +0 -0
- arctrl/py/Spreadsheet/arc_assay.py +233 -0
- arctrl/py/Spreadsheet/arc_investigation.py +418 -0
- arctrl/py/Spreadsheet/arc_run.py +190 -0
- arctrl/py/Spreadsheet/arc_study.py +144 -0
- arctrl/py/Spreadsheet/arc_workflow.py +176 -0
- arctrl/py/Spreadsheet/assembly_info.py +1 -0
- arctrl/py/Spreadsheet/collection_aux.py +167 -0
- arctrl/py/Spreadsheet/data_map.py +44 -0
- arctrl/py/Spreadsheet/template.py +460 -0
- arctrl/py/ValidationPackages/__init__.py +0 -0
- arctrl/py/ValidationPackages/validation_package.py +82 -0
- arctrl/py/ValidationPackages/validation_packages_config.py +132 -0
- arctrl/py/WebRequest/__init__.py +0 -0
- arctrl/py/WebRequest/web_request.py +9 -0
- arctrl/py/WebRequest/web_request_py.py +135 -0
- arctrl/py/Yaml/__init__.py +0 -0
- arctrl/py/Yaml/decode.py +1 -0
- arctrl/py/Yaml/encode.py +10 -0
- arctrl/py/Yaml/validation_package.py +77 -0
- arctrl/py/Yaml/validation_packages_config.py +86 -0
- arctrl/py/__init__.py +0 -0
- arctrl/py/arc.py +1400 -0
- arctrl/py/column_index.py +280 -0
- arctrl/py/conversion.py +2184 -0
- arctrl/py/cross_async.py +76 -0
- arctrl/py/fable_modules/dynamic_obj/__init__.py +0 -0
- arctrl/py/fable_modules/dynamic_obj/dyn_obj.py +136 -0
- arctrl/py/fable_modules/dynamic_obj/dynamic_obj.py +415 -0
- arctrl/py/fable_modules/dynamic_obj/fable_js.py +1 -0
- arctrl/py/fable_modules/dynamic_obj/fable_py.py +288 -0
- arctrl/py/fable_modules/dynamic_obj/hash_codes.py +82 -0
- arctrl/py/fable_modules/dynamic_obj/property_helper.py +25 -0
- arctrl/py/fable_modules/dynamic_obj/reflection_utils.py +87 -0
- arctrl/py/fable_modules/fable_library/__init__.py +0 -0
- arctrl/py/fable_modules/fable_library/array_.py +1528 -0
- arctrl/py/fable_modules/fable_library/async_.py +377 -0
- arctrl/py/fable_modules/fable_library/async_builder.py +379 -0
- arctrl/py/fable_modules/fable_library/big_int.py +330 -0
- arctrl/py/fable_modules/fable_library/bit_converter.py +131 -0
- arctrl/py/fable_modules/fable_library/boolean.py +26 -0
- arctrl/py/fable_modules/fable_library/char.py +237 -0
- arctrl/py/fable_modules/fable_library/choice.py +212 -0
- arctrl/py/fable_modules/fable_library/date.py +779 -0
- arctrl/py/fable_modules/fable_library/date_offset.py +79 -0
- arctrl/py/fable_modules/fable_library/decimal_.py +190 -0
- arctrl/py/fable_modules/fable_library/diagnostics.py +54 -0
- arctrl/py/fable_modules/fable_library/double.py +87 -0
- arctrl/py/fable_modules/fable_library/encoding.py +41 -0
- arctrl/py/fable_modules/fable_library/event.py +206 -0
- arctrl/py/fable_modules/fable_library/file.py +107 -0
- arctrl/py/fable_modules/fable_library/fsharp_collections.py +52 -0
- arctrl/py/fable_modules/fable_library/fsharp_core.py +123 -0
- arctrl/py/fable_modules/fable_library/global_.py +63 -0
- arctrl/py/fable_modules/fable_library/guid.py +41 -0
- arctrl/py/fable_modules/fable_library/int32.py +73 -0
- arctrl/py/fable_modules/fable_library/list.py +1788 -0
- arctrl/py/fable_modules/fable_library/long.py +240 -0
- arctrl/py/fable_modules/fable_library/mailbox_processor.py +179 -0
- arctrl/py/fable_modules/fable_library/map.py +1854 -0
- arctrl/py/fable_modules/fable_library/map_util.py +148 -0
- arctrl/py/fable_modules/fable_library/mutable_map.py +397 -0
- arctrl/py/fable_modules/fable_library/mutable_set.py +279 -0
- arctrl/py/fable_modules/fable_library/native.py +45 -0
- arctrl/py/fable_modules/fable_library/numeric.py +46 -0
- arctrl/py/fable_modules/fable_library/observable.py +222 -0
- arctrl/py/fable_modules/fable_library/option.py +128 -0
- arctrl/py/fable_modules/fable_library/path.py +62 -0
- arctrl/py/fable_modules/fable_library/range.py +117 -0
- arctrl/py/fable_modules/fable_library/reflection.py +463 -0
- arctrl/py/fable_modules/fable_library/reg_exp.py +137 -0
- arctrl/py/fable_modules/fable_library/resize_array.py +31 -0
- arctrl/py/fable_modules/fable_library/result.py +212 -0
- arctrl/py/fable_modules/fable_library/seq.py +1979 -0
- arctrl/py/fable_modules/fable_library/seq2.py +221 -0
- arctrl/py/fable_modules/fable_library/set.py +2414 -0
- arctrl/py/fable_modules/fable_library/singleton_local_time_zone.py +36 -0
- arctrl/py/fable_modules/fable_library/string_.py +573 -0
- arctrl/py/fable_modules/fable_library/system_collections_generic.py +462 -0
- arctrl/py/fable_modules/fable_library/system_text.py +237 -0
- arctrl/py/fable_modules/fable_library/task.py +116 -0
- arctrl/py/fable_modules/fable_library/task_builder.py +122 -0
- arctrl/py/fable_modules/fable_library/thread.py +5 -0
- arctrl/py/fable_modules/fable_library/time_span.py +283 -0
- arctrl/py/fable_modules/fable_library/timer.py +24 -0
- arctrl/py/fable_modules/fable_library/types.py +401 -0
- arctrl/py/fable_modules/fable_library/uri.py +109 -0
- arctrl/py/fable_modules/fable_library/util.py +2735 -0
- arctrl/py/fable_modules/fable_openpyxl/__init__.py +0 -0
- arctrl/py/fable_modules/fable_openpyxl/openpyxl.py +362 -0
- arctrl/py/fable_modules/fable_python/cognite-sdk/__init__.py +0 -0
- arctrl/py/fable_modules/fable_python/cognite-sdk/cognite_sdk.py +22 -0
- arctrl/py/fable_modules/fable_python/flask/__init__.py +0 -0
- arctrl/py/fable_modules/fable_python/flask/flask.py +34 -0
- arctrl/py/fable_modules/fable_python/jupyter/__init__.py +0 -0
- arctrl/py/fable_modules/fable_python/jupyter/ipy_widgets.py +47 -0
- arctrl/py/fable_modules/fable_python/jupyter/ipython.py +13 -0
- arctrl/py/fable_modules/fable_python/stdlib/__init__.py +0 -0
- arctrl/py/fable_modules/fable_python/stdlib/ast.py +1 -0
- arctrl/py/fable_modules/fable_python/stdlib/asyncio/__init__.py +0 -0
- arctrl/py/fable_modules/fable_python/stdlib/asyncio/events.py +17 -0
- arctrl/py/fable_modules/fable_python/stdlib/asyncio/futures.py +52 -0
- arctrl/py/fable_modules/fable_python/stdlib/asyncio/tasks.py +38 -0
- arctrl/py/fable_modules/fable_python/stdlib/base64_.py +1 -0
- arctrl/py/fable_modules/fable_python/stdlib/builtins_.py +38 -0
- arctrl/py/fable_modules/fable_python/stdlib/html.py +1 -0
- arctrl/py/fable_modules/fable_python/stdlib/json.py +1 -0
- arctrl/py/fable_modules/fable_python/stdlib/math_.py +1 -0
- arctrl/py/fable_modules/fable_python/stdlib/os_.py +1 -0
- arctrl/py/fable_modules/fable_python/stdlib/queue_.py +1 -0
- arctrl/py/fable_modules/fable_python/stdlib/string_.py +1 -0
- arctrl/py/fable_modules/fable_python/stdlib/sys_.py +30 -0
- arctrl/py/fable_modules/fable_python/stdlib/time_.py +1 -0
- arctrl/py/fable_modules/fable_python/stdlib/tk_inter.py +1 -0
- arctrl/py/fable_modules/fs_spreadsheet/Cells/__init__.py +0 -0
- arctrl/py/fable_modules/fs_spreadsheet/Cells/fs_cell.py +338 -0
- arctrl/py/fable_modules/fs_spreadsheet/Cells/fs_cells_collection.py +469 -0
- arctrl/py/fable_modules/fs_spreadsheet/DSL/__init__.py +0 -0
- arctrl/py/fable_modules/fs_spreadsheet/DSL/cell_builder.py +214 -0
- arctrl/py/fable_modules/fs_spreadsheet/DSL/column_builder.py +139 -0
- arctrl/py/fable_modules/fs_spreadsheet/DSL/dsl.py +50 -0
- arctrl/py/fable_modules/fs_spreadsheet/DSL/expression.py +65 -0
- arctrl/py/fable_modules/fs_spreadsheet/DSL/operators.py +9 -0
- arctrl/py/fable_modules/fs_spreadsheet/DSL/row_builder.py +139 -0
- arctrl/py/fable_modules/fs_spreadsheet/DSL/sheet_builder.py +118 -0
- arctrl/py/fable_modules/fs_spreadsheet/DSL/table_builder.py +122 -0
- arctrl/py/fable_modules/fs_spreadsheet/DSL/transform.py +464 -0
- arctrl/py/fable_modules/fs_spreadsheet/DSL/types.py +314 -0
- arctrl/py/fable_modules/fs_spreadsheet/DSL/workbook_builder.py +106 -0
- arctrl/py/fable_modules/fs_spreadsheet/Json/__init__.py +0 -0
- arctrl/py/fable_modules/fs_spreadsheet/Json/cell.py +103 -0
- arctrl/py/fable_modules/fs_spreadsheet/Json/column.py +70 -0
- arctrl/py/fable_modules/fs_spreadsheet/Json/row.py +70 -0
- arctrl/py/fable_modules/fs_spreadsheet/Json/table.py +57 -0
- arctrl/py/fable_modules/fs_spreadsheet/Json/value.py +93 -0
- arctrl/py/fable_modules/fs_spreadsheet/Json/workbook.py +71 -0
- arctrl/py/fable_modules/fs_spreadsheet/Json/worksheet.py +217 -0
- arctrl/py/fable_modules/fs_spreadsheet/Ranges/__init__.py +0 -0
- arctrl/py/fable_modules/fs_spreadsheet/Ranges/fs_range.py +47 -0
- arctrl/py/fable_modules/fs_spreadsheet/Ranges/fs_range_address.py +186 -0
- arctrl/py/fable_modules/fs_spreadsheet/Ranges/fs_range_base.py +90 -0
- arctrl/py/fable_modules/fs_spreadsheet/Ranges/fs_range_column.py +78 -0
- arctrl/py/fable_modules/fs_spreadsheet/Ranges/fs_range_row.py +48 -0
- arctrl/py/fable_modules/fs_spreadsheet/Tables/__init__.py +0 -0
- arctrl/py/fable_modules/fs_spreadsheet/Tables/fs_table.py +393 -0
- arctrl/py/fable_modules/fs_spreadsheet/Tables/fs_table_field.py +127 -0
- arctrl/py/fable_modules/fs_spreadsheet/Tables/fs_table_row.py +23 -0
- arctrl/py/fable_modules/fs_spreadsheet/__init__.py +0 -0
- arctrl/py/fable_modules/fs_spreadsheet/fs_address.py +218 -0
- arctrl/py/fable_modules/fs_spreadsheet/fs_column.py +172 -0
- arctrl/py/fable_modules/fs_spreadsheet/fs_row.py +183 -0
- arctrl/py/fable_modules/fs_spreadsheet/fs_workbook.py +180 -0
- arctrl/py/fable_modules/fs_spreadsheet/fs_worksheet.py +600 -0
- arctrl/py/fable_modules/fs_spreadsheet/sheet_builder.py +330 -0
- arctrl/py/fable_modules/fs_spreadsheet_py/__init__.py +0 -0
- arctrl/py/fable_modules/fs_spreadsheet_py/cell.py +63 -0
- arctrl/py/fable_modules/fs_spreadsheet_py/cell_type.py +50 -0
- arctrl/py/fable_modules/fs_spreadsheet_py/fs_extension.py +60 -0
- arctrl/py/fable_modules/fs_spreadsheet_py/json.py +47 -0
- arctrl/py/fable_modules/fs_spreadsheet_py/table.py +53 -0
- arctrl/py/fable_modules/fs_spreadsheet_py/workbook.py +40 -0
- arctrl/py/fable_modules/fs_spreadsheet_py/worksheet.py +54 -0
- arctrl/py/fable_modules/fs_spreadsheet_py/xlsx.py +37 -0
- arctrl/py/fable_modules/thoth_json_core/__init__.py +0 -0
- arctrl/py/fable_modules/thoth_json_core/decode.py +1588 -0
- arctrl/py/fable_modules/thoth_json_core/encode.py +261 -0
- arctrl/py/fable_modules/thoth_json_core/types.py +181 -0
- arctrl/py/fable_modules/thoth_json_python/__init__.py +0 -0
- arctrl/py/fable_modules/thoth_json_python/decode.py +112 -0
- arctrl/py/fable_modules/thoth_json_python/encode.py +72 -0
- arctrl/py/fable_modules/thoth_json_python/python.py +1 -0
- arctrl/py/fable_modules/yamlicious/Interop/__init__.py +0 -0
- arctrl/py/fable_modules/yamlicious/Interop/js_interop.py +1 -0
- arctrl/py/fable_modules/yamlicious/Interop/py_interop.py +7 -0
- arctrl/py/fable_modules/yamlicious/__init__.py +0 -0
- arctrl/py/fable_modules/yamlicious/decode.py +1784 -0
- arctrl/py/fable_modules/yamlicious/encode.py +84 -0
- arctrl/py/fable_modules/yamlicious/library.py +10 -0
- arctrl/py/fable_modules/yamlicious/persil.py +57 -0
- arctrl/py/fable_modules/yamlicious/preprocessing.py +99 -0
- arctrl/py/fable_modules/yamlicious/reader.py +665 -0
- arctrl/py/fable_modules/yamlicious/regex.py +21 -0
- arctrl/py/fable_modules/yamlicious/regex_active_patterns.py +256 -0
- arctrl/py/fable_modules/yamlicious/writer.py +175 -0
- arctrl/py/fable_modules/yamlicious/yamlicious_types.py +128 -0
- arctrl/py/json.py +213 -0
- arctrl/py/rocrate_io.py +72 -0
- arctrl/py/template_web.py +23 -0
- arctrl/py/xlsx.py +148 -0
- arctrl/rocrate.py +21 -0
- arctrl-3.0.0a3.dist-info/LICENSE +21 -0
- arctrl-3.0.0a3.dist-info/METADATA +119 -0
- arctrl-3.0.0a3.dist-info/RECORD +456 -0
- arctrl-3.0.0a3.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,779 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
from datetime import datetime, timedelta, timezone
|
|
5
|
+
from math import fmod
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from .singleton_local_time_zone import local_time_zone
|
|
9
|
+
from .time_span import TimeSpan, total_microseconds
|
|
10
|
+
from .time_span import create as create_time_span
|
|
11
|
+
from .types import FSharpRef
|
|
12
|
+
from .util import DateKind
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# Some of the code in this file has been adapted from
|
|
16
|
+
# https://github.com/microsoft/referencesource/blob/51cf7850defa8a17d815b4700b67116e3fa283c2/mscorlib/system/globalization/datetimeformat.cs
|
|
17
|
+
|
|
18
|
+
short_days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
|
|
19
|
+
|
|
20
|
+
long_days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
|
|
21
|
+
|
|
22
|
+
short_months = [
|
|
23
|
+
"Jan",
|
|
24
|
+
"Feb",
|
|
25
|
+
"Mar",
|
|
26
|
+
"Apr",
|
|
27
|
+
"May",
|
|
28
|
+
"Jun",
|
|
29
|
+
"Jul",
|
|
30
|
+
"Aug",
|
|
31
|
+
"Sep",
|
|
32
|
+
"Oct",
|
|
33
|
+
"Nov",
|
|
34
|
+
"Dec",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
long_months = [
|
|
38
|
+
"January",
|
|
39
|
+
"February",
|
|
40
|
+
"March",
|
|
41
|
+
"April",
|
|
42
|
+
"May",
|
|
43
|
+
"June",
|
|
44
|
+
"July",
|
|
45
|
+
"August",
|
|
46
|
+
"September",
|
|
47
|
+
"October",
|
|
48
|
+
"November",
|
|
49
|
+
"December",
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def subtract(x: datetime, y: datetime | TimeSpan) -> datetime | TimeSpan:
|
|
54
|
+
if isinstance(y, datetime):
|
|
55
|
+
delta = x - y
|
|
56
|
+
# ts.microseconds only contains the microseconds provided to the constructor
|
|
57
|
+
# so we need to calculate the total microseconds ourselves
|
|
58
|
+
delta_microseconds = delta.days * (24 * 3600 * 10**6) + delta.seconds * 10**6 + delta.microseconds
|
|
59
|
+
return create_time_span(0, 0, 0, 0, 0, delta_microseconds)
|
|
60
|
+
|
|
61
|
+
return x - timedelta(microseconds=total_microseconds(y))
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def op_subtraction(x: datetime, y: datetime | TimeSpan) -> datetime | TimeSpan:
|
|
65
|
+
return subtract(x, y)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def create(
|
|
69
|
+
year: int,
|
|
70
|
+
month: int,
|
|
71
|
+
day: int,
|
|
72
|
+
h: int = 0,
|
|
73
|
+
m: int = 0,
|
|
74
|
+
s: int = 0,
|
|
75
|
+
ms: int = 0,
|
|
76
|
+
mc: int = 0,
|
|
77
|
+
kind: DateKind | None = None,
|
|
78
|
+
) -> datetime:
|
|
79
|
+
if kind == DateKind.UTC:
|
|
80
|
+
date = datetime(
|
|
81
|
+
year=year,
|
|
82
|
+
month=month,
|
|
83
|
+
day=day,
|
|
84
|
+
hour=h,
|
|
85
|
+
minute=m,
|
|
86
|
+
second=s,
|
|
87
|
+
microsecond=mc + ms * 1_000,
|
|
88
|
+
tzinfo=timezone.utc,
|
|
89
|
+
)
|
|
90
|
+
else:
|
|
91
|
+
date = datetime(year, month, day, h, m, s, mc + ms * 1_000)
|
|
92
|
+
if kind == DateKind.Local:
|
|
93
|
+
date = date.astimezone(local_time_zone)
|
|
94
|
+
|
|
95
|
+
return date
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def year(d: datetime) -> int:
|
|
99
|
+
return d.year
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def month(d: datetime) -> int:
|
|
103
|
+
return d.month
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def day(d: datetime) -> int:
|
|
107
|
+
return d.day
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def hour(d: datetime) -> int:
|
|
111
|
+
return d.hour
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def minute(d: datetime) -> int:
|
|
115
|
+
return d.minute
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def second(d: datetime) -> int:
|
|
119
|
+
return d.second
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def millisecond(d: datetime) -> int:
|
|
123
|
+
return d.microsecond // 1_000
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def microsecond(d: datetime) -> int:
|
|
127
|
+
return d.microsecond
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def to_universal_time(d: datetime) -> datetime:
|
|
131
|
+
return d.astimezone(timezone.utc)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def day_of_week(d: datetime) -> int:
|
|
135
|
+
return (d.weekday() + 1) % 7
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def day_of_year(d: datetime) -> int:
|
|
139
|
+
return d.timetuple().tm_yday
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def to_short_date_string(date: datetime) -> str:
|
|
143
|
+
return datetime.strftime(date, "%m/%d/%Y")
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def to_long_date_string(date: datetime) -> str:
|
|
147
|
+
return datetime.strftime(date, "%A, %d %B %Y")
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def to_short_time_string(date: datetime) -> str:
|
|
151
|
+
return datetime.strftime(date, "%H:%M")
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def to_long_time_string(date: datetime) -> str:
|
|
155
|
+
return datetime.strftime(date, "%H:%M:%S")
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def parse_repeat_token(format: str, pos: int, pattern_char: str) -> int:
|
|
159
|
+
token_length = 0
|
|
160
|
+
internal_pos = pos
|
|
161
|
+
while internal_pos < len(format) and format[internal_pos] == pattern_char:
|
|
162
|
+
internal_pos += 1
|
|
163
|
+
token_length += 1
|
|
164
|
+
|
|
165
|
+
return token_length
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
# Get the next character at the index of 'pos' in the 'format' string.
|
|
169
|
+
# Return value of -1 means 'pos' is already at the end of the 'format' string.
|
|
170
|
+
# Otherwise, return value is the int value of the next character.
|
|
171
|
+
def parse_next_char(format: str, pos: int) -> int:
|
|
172
|
+
if pos >= len(format) - 1:
|
|
173
|
+
return -1
|
|
174
|
+
|
|
175
|
+
return ord(format[pos + 1])
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def parse_quoted_string(format: str, pos: int) -> tuple[str, int]:
|
|
179
|
+
begin_pos = pos
|
|
180
|
+
format_length = len(format)
|
|
181
|
+
# Get the character used to quote the string
|
|
182
|
+
quote_char = format[pos]
|
|
183
|
+
|
|
184
|
+
result = ""
|
|
185
|
+
found_quote = False
|
|
186
|
+
|
|
187
|
+
while pos < format_length:
|
|
188
|
+
pos += 1
|
|
189
|
+
current_char = format[pos]
|
|
190
|
+
if current_char == quote_char:
|
|
191
|
+
found_quote = True
|
|
192
|
+
break
|
|
193
|
+
elif current_char == "\\":
|
|
194
|
+
if pos < format_length:
|
|
195
|
+
pos += 1
|
|
196
|
+
result += format[pos]
|
|
197
|
+
else:
|
|
198
|
+
# This means that '\'is the last character in the format string.
|
|
199
|
+
raise ValueError("Invalid string format")
|
|
200
|
+
else:
|
|
201
|
+
result += current_char
|
|
202
|
+
|
|
203
|
+
if not found_quote:
|
|
204
|
+
# We couldn't find the matching quote
|
|
205
|
+
raise ValueError(f"Invalid string format could not find matching quote for {quote_char}")
|
|
206
|
+
|
|
207
|
+
return (result, pos - begin_pos + 1)
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def date_to_string_with_custom_format(date: datetime, format: str, utc: bool) -> str:
|
|
211
|
+
cursor_pos = 0
|
|
212
|
+
token_length = 0
|
|
213
|
+
result = ""
|
|
214
|
+
localized_date = date.astimezone(timezone.utc) if utc else date
|
|
215
|
+
|
|
216
|
+
while cursor_pos < len(format):
|
|
217
|
+
token = format[cursor_pos]
|
|
218
|
+
|
|
219
|
+
match token:
|
|
220
|
+
case "d":
|
|
221
|
+
token_length = parse_repeat_token(format, cursor_pos, "d")
|
|
222
|
+
cursor_pos += token_length
|
|
223
|
+
match token_length:
|
|
224
|
+
case 1:
|
|
225
|
+
result += str(localized_date.day)
|
|
226
|
+
case 2:
|
|
227
|
+
result += localized_date.strftime("%d")
|
|
228
|
+
case 3:
|
|
229
|
+
result += short_days[day_of_week(localized_date)]
|
|
230
|
+
case 4:
|
|
231
|
+
result += long_days[day_of_week(localized_date)]
|
|
232
|
+
case _:
|
|
233
|
+
pass
|
|
234
|
+
case "f":
|
|
235
|
+
token_length = parse_repeat_token(format, cursor_pos, "f")
|
|
236
|
+
cursor_pos += token_length
|
|
237
|
+
match token_length:
|
|
238
|
+
case 1 | 2 | 3 | 4 | 5 | 6:
|
|
239
|
+
precision = 10 ** (6 - token_length)
|
|
240
|
+
result += str(localized_date.microsecond // precision).zfill(token_length)
|
|
241
|
+
# Python datetime only support precision up to the microsecond
|
|
242
|
+
# so we need to fill the rest with 0
|
|
243
|
+
case 7:
|
|
244
|
+
result += str(localized_date.microsecond).zfill(6).ljust(token_length, "0")
|
|
245
|
+
case _:
|
|
246
|
+
pass
|
|
247
|
+
case "F":
|
|
248
|
+
token_length = parse_repeat_token(format, cursor_pos, "F")
|
|
249
|
+
cursor_pos += token_length
|
|
250
|
+
match token_length:
|
|
251
|
+
case 1 | 2 | 3 | 4 | 5 | 6:
|
|
252
|
+
precision = 10 ** (6 - token_length)
|
|
253
|
+
value = localized_date.microsecond // precision
|
|
254
|
+
if value != 0:
|
|
255
|
+
result += str(value).zfill(token_length)
|
|
256
|
+
# Python datetime only support precision up to the microsecond
|
|
257
|
+
# so we can't go further
|
|
258
|
+
# We alse need to pad start with 0 if the value is not 0
|
|
259
|
+
case 7:
|
|
260
|
+
value = localized_date.microsecond
|
|
261
|
+
if value != 0:
|
|
262
|
+
result += str(value).zfill(6).rstrip("0")
|
|
263
|
+
case _:
|
|
264
|
+
pass
|
|
265
|
+
case "g":
|
|
266
|
+
token_length = parse_repeat_token(format, cursor_pos, "g")
|
|
267
|
+
cursor_pos += token_length
|
|
268
|
+
match token_length:
|
|
269
|
+
case 1 | 2:
|
|
270
|
+
result += "A.D."
|
|
271
|
+
case _:
|
|
272
|
+
pass
|
|
273
|
+
|
|
274
|
+
case "h":
|
|
275
|
+
token_length = parse_repeat_token(format, cursor_pos, "h")
|
|
276
|
+
cursor_pos += token_length
|
|
277
|
+
match token_length:
|
|
278
|
+
case 1:
|
|
279
|
+
result += str(localized_date.hour % 12)
|
|
280
|
+
case 2:
|
|
281
|
+
result += localized_date.strftime("%I")
|
|
282
|
+
case _:
|
|
283
|
+
pass
|
|
284
|
+
case "H":
|
|
285
|
+
token_length = parse_repeat_token(format, cursor_pos, "H")
|
|
286
|
+
cursor_pos += token_length
|
|
287
|
+
match token_length:
|
|
288
|
+
case 1:
|
|
289
|
+
result += str(localized_date.hour)
|
|
290
|
+
case 2:
|
|
291
|
+
result += localized_date.strftime("%H")
|
|
292
|
+
case _:
|
|
293
|
+
pass
|
|
294
|
+
case "K":
|
|
295
|
+
token_length = parse_repeat_token(format, cursor_pos, "K")
|
|
296
|
+
cursor_pos += token_length
|
|
297
|
+
match token_length:
|
|
298
|
+
case 1:
|
|
299
|
+
match kind(date):
|
|
300
|
+
case DateKind.UTC:
|
|
301
|
+
result += "Z"
|
|
302
|
+
case DateKind.Local:
|
|
303
|
+
# %:z is not a perfect match for the .NET equivalent
|
|
304
|
+
# but it seems to do the job
|
|
305
|
+
# If needed we can probably compute the offset manually
|
|
306
|
+
# and format it ourselves
|
|
307
|
+
result += date.strftime("%:z")
|
|
308
|
+
case DateKind.Unspecified:
|
|
309
|
+
result += ""
|
|
310
|
+
case _:
|
|
311
|
+
pass
|
|
312
|
+
case "m":
|
|
313
|
+
token_length = parse_repeat_token(format, cursor_pos, "m")
|
|
314
|
+
cursor_pos += token_length
|
|
315
|
+
match token_length:
|
|
316
|
+
case 1:
|
|
317
|
+
result += str(localized_date.minute)
|
|
318
|
+
case 2:
|
|
319
|
+
result += localized_date.strftime("%M")
|
|
320
|
+
case _:
|
|
321
|
+
pass
|
|
322
|
+
case "M":
|
|
323
|
+
token_length = parse_repeat_token(format, cursor_pos, "M")
|
|
324
|
+
cursor_pos += token_length
|
|
325
|
+
match token_length:
|
|
326
|
+
case 1:
|
|
327
|
+
result += str(localized_date.month)
|
|
328
|
+
case 2:
|
|
329
|
+
result += localized_date.strftime("%m")
|
|
330
|
+
case 3:
|
|
331
|
+
result += short_months[month(localized_date) - 1]
|
|
332
|
+
case 4:
|
|
333
|
+
result += long_months[month(localized_date) - 1]
|
|
334
|
+
case _:
|
|
335
|
+
pass
|
|
336
|
+
case "s":
|
|
337
|
+
token_length = parse_repeat_token(format, cursor_pos, "s")
|
|
338
|
+
cursor_pos += token_length
|
|
339
|
+
match token_length:
|
|
340
|
+
case 1:
|
|
341
|
+
result += str(localized_date.second)
|
|
342
|
+
case 2:
|
|
343
|
+
result += localized_date.strftime("%S")
|
|
344
|
+
case _:
|
|
345
|
+
pass
|
|
346
|
+
case "t":
|
|
347
|
+
token_length = parse_repeat_token(format, cursor_pos, "t")
|
|
348
|
+
cursor_pos += token_length
|
|
349
|
+
match token_length:
|
|
350
|
+
case 1:
|
|
351
|
+
result += localized_date.strftime("%p")[:1]
|
|
352
|
+
case 2:
|
|
353
|
+
result += localized_date.strftime("%p")
|
|
354
|
+
case _:
|
|
355
|
+
pass
|
|
356
|
+
case "y":
|
|
357
|
+
token_length = parse_repeat_token(format, cursor_pos, "y")
|
|
358
|
+
cursor_pos += token_length
|
|
359
|
+
match token_length:
|
|
360
|
+
case 1:
|
|
361
|
+
result += str(localized_date.year % 100)
|
|
362
|
+
case 2:
|
|
363
|
+
result += str(localized_date.year)[-2:].zfill(2)
|
|
364
|
+
case length:
|
|
365
|
+
result += str(localized_date.year).zfill(length)
|
|
366
|
+
case "z":
|
|
367
|
+
token_length = parse_repeat_token(format, cursor_pos, "z")
|
|
368
|
+
cursor_pos += token_length
|
|
369
|
+
|
|
370
|
+
match kind(date):
|
|
371
|
+
case DateKind.UTC:
|
|
372
|
+
utc_offet_text = localized_date.strftime("%z")
|
|
373
|
+
case DateKind.Local:
|
|
374
|
+
utc_offet_text = localized_date.strftime("%z")
|
|
375
|
+
case DateKind.Unspecified:
|
|
376
|
+
utc_offet_text = to_local_time(date).strftime("%z")
|
|
377
|
+
|
|
378
|
+
sign = utc_offet_text[:1]
|
|
379
|
+
hours = int(utc_offet_text[1:3])
|
|
380
|
+
minutes = int(utc_offet_text[3:5])
|
|
381
|
+
|
|
382
|
+
match token_length:
|
|
383
|
+
case 1:
|
|
384
|
+
result += f"{sign}{hours}"
|
|
385
|
+
case 2:
|
|
386
|
+
result += f"{sign}{hours:02}"
|
|
387
|
+
case 3 | _:
|
|
388
|
+
result += f"{sign}{hours:02}:{minutes:02}"
|
|
389
|
+
case ":":
|
|
390
|
+
cursor_pos += 1
|
|
391
|
+
result += ":"
|
|
392
|
+
case "/":
|
|
393
|
+
cursor_pos += 1
|
|
394
|
+
result += "/"
|
|
395
|
+
case "'" | '"':
|
|
396
|
+
quoted_string, quoted_string_length = parse_quoted_string(format, cursor_pos)
|
|
397
|
+
cursor_pos += quoted_string_length
|
|
398
|
+
result += quoted_string
|
|
399
|
+
case "%":
|
|
400
|
+
next_char = parse_next_char(format, cursor_pos)
|
|
401
|
+
if next_char >= 0 and next_char != ord("%"):
|
|
402
|
+
cursor_pos += 2
|
|
403
|
+
result += date_to_string_with_custom_format(date, chr(next_char), utc)
|
|
404
|
+
else:
|
|
405
|
+
raise Exception("Invalid string format")
|
|
406
|
+
case "\\":
|
|
407
|
+
next_char = parse_next_char(format, cursor_pos)
|
|
408
|
+
if next_char >= 0:
|
|
409
|
+
result += chr(next_char)
|
|
410
|
+
cursor_pos += 2
|
|
411
|
+
else:
|
|
412
|
+
raise Exception("Invalid string format")
|
|
413
|
+
case _:
|
|
414
|
+
cursor_pos += 1
|
|
415
|
+
result += token
|
|
416
|
+
pass
|
|
417
|
+
|
|
418
|
+
return result
|
|
419
|
+
|
|
420
|
+
|
|
421
|
+
def date_to_string_with_offset(date: datetime, format: str | None = None) -> str:
|
|
422
|
+
utc = date.tzinfo == timezone.utc
|
|
423
|
+
|
|
424
|
+
match format:
|
|
425
|
+
case None:
|
|
426
|
+
raise NotImplementedError("date_to_string_with_offset")
|
|
427
|
+
case "O" | "o":
|
|
428
|
+
return date.strftime("%Y-%m-%dT%H:%M:%S.%fZ")
|
|
429
|
+
case _ if len(format) == 1:
|
|
430
|
+
raise Exception("Unrecognized Date print format")
|
|
431
|
+
case _:
|
|
432
|
+
return date_to_string_with_custom_format(date, format, utc)
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
def date_to_string_with_kind(date: datetime, format: str | None = None) -> str:
|
|
436
|
+
utc = date.tzinfo == timezone.utc
|
|
437
|
+
|
|
438
|
+
if not format:
|
|
439
|
+
return date.isoformat() if utc else str(date)
|
|
440
|
+
elif len(format) == 1:
|
|
441
|
+
if format == "d":
|
|
442
|
+
return to_short_date_string(date)
|
|
443
|
+
elif format == "D":
|
|
444
|
+
return to_long_date_string(date)
|
|
445
|
+
elif format == "T":
|
|
446
|
+
return to_long_time_string(date)
|
|
447
|
+
elif format == "t":
|
|
448
|
+
return to_short_time_string(date)
|
|
449
|
+
elif format == "O" or format == "o":
|
|
450
|
+
return date.astimezone().isoformat(timespec="milliseconds")
|
|
451
|
+
else:
|
|
452
|
+
raise Exception("Unrecognized Date print format")
|
|
453
|
+
|
|
454
|
+
else:
|
|
455
|
+
return date_to_string_with_custom_format(date, format, utc)
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
def to_string(date: datetime, format: str | None = None, provider: Any | None = None) -> str:
|
|
459
|
+
if date.tzinfo:
|
|
460
|
+
return date_to_string_with_offset(date, format)
|
|
461
|
+
|
|
462
|
+
return date_to_string_with_kind(date, format)
|
|
463
|
+
|
|
464
|
+
|
|
465
|
+
def now() -> datetime:
|
|
466
|
+
return datetime.now()
|
|
467
|
+
|
|
468
|
+
|
|
469
|
+
def utc_now() -> datetime:
|
|
470
|
+
return datetime.utcnow()
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
def today() -> datetime:
|
|
474
|
+
return datetime.replace(now(), hour=0, minute=0, second=0, microsecond=0)
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
def to_local_time(date: datetime) -> datetime:
|
|
478
|
+
return date.astimezone().replace(tzinfo=local_time_zone)
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
def compare(x: datetime, y: datetime) -> int:
|
|
482
|
+
if x == y:
|
|
483
|
+
return 0
|
|
484
|
+
|
|
485
|
+
if x < y:
|
|
486
|
+
return -1
|
|
487
|
+
|
|
488
|
+
return 1
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
def equals(x: datetime, y: datetime) -> bool:
|
|
492
|
+
return x == y
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
def max_value() -> datetime:
|
|
496
|
+
return datetime.max
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
def min_value() -> datetime:
|
|
500
|
+
return datetime.min
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
def op_addition(x: datetime, y: TimeSpan) -> datetime:
|
|
504
|
+
return x + timedelta(microseconds=total_microseconds(y))
|
|
505
|
+
|
|
506
|
+
|
|
507
|
+
def add(x: datetime, y: TimeSpan) -> datetime:
|
|
508
|
+
return op_addition(x, y)
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
def parse(string: str) -> datetime:
|
|
512
|
+
try:
|
|
513
|
+
return datetime.fromisoformat(string).astimezone()
|
|
514
|
+
except ValueError:
|
|
515
|
+
pass
|
|
516
|
+
|
|
517
|
+
# For the time-only formats, needs a special treatment
|
|
518
|
+
# because in Python, they are set in 1900-01-01 while
|
|
519
|
+
# in F# they are set in the current date
|
|
520
|
+
hoursFormats = {
|
|
521
|
+
# Matches a time string in 24-hour format "HH:MM:SS"
|
|
522
|
+
r"^\d{1,2}:\d{1,2}:\d{2}$": "%H:%M:%S",
|
|
523
|
+
# Matches a time string in 12-hour format with AM/PM "HH:MM:SS AM" or "HH:MM:SS PM"
|
|
524
|
+
r"^(0?[1-9]|1[0-2]):([0-5][1-9]|0?[0-9]):([0-5][0-9]|0?[0-9]) [AP]M$": "%I:%M:%S %p",
|
|
525
|
+
r"^\d{1,2}:\d{1,2}:\d{2} [AP]M$": "%H:%M:%S %p",
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
for pattern, format in hoursFormats.items():
|
|
529
|
+
if re.fullmatch(pattern, string):
|
|
530
|
+
hourDate = datetime.strptime(string, format)
|
|
531
|
+
|
|
532
|
+
# If the hour is 0 PM, then in .NET it is 12 PM (python keeps it as 0)
|
|
533
|
+
hourOffset = 12 if hourDate.hour == 0 and string.endswith(" PM") else 0
|
|
534
|
+
|
|
535
|
+
return datetime.replace(
|
|
536
|
+
now(),
|
|
537
|
+
hour=hourDate.hour + hourOffset,
|
|
538
|
+
minute=hourDate.minute,
|
|
539
|
+
second=hourDate.second,
|
|
540
|
+
microsecond=0,
|
|
541
|
+
)
|
|
542
|
+
|
|
543
|
+
formats = {
|
|
544
|
+
# 9/10/2014 1:50:34 PM
|
|
545
|
+
r"^(0?[1-9]|1[0-2])\/(0?[1-9]|1[0-2])\/\d{4} ([0-9]|(0|1)[0-9]|2[0-4]):([0-5][0-9]|0?[0-9]):([0-5][0-9]|0?[0-9]) [AP]M$": "%m/%d/%Y %I:%M:%S %p",
|
|
546
|
+
# 9/10/2014 1:50:34
|
|
547
|
+
r"^(0?[1-9]|1[0-2])\/(0?[1-9]|1[0-2])\/\d{4} ([0-9]|(0|1)[0-9]|2[0-4]):([0-5][0-9]|0?[0-9]):([0-5][0-9]|0?[0-9])$": "%m/%d/%Y %H:%M:%S",
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
for pattern, format in formats.items():
|
|
551
|
+
if re.fullmatch(pattern, string):
|
|
552
|
+
return datetime.strptime(string, format)
|
|
553
|
+
|
|
554
|
+
# Matches a datetime string in the format "YYYY-MM-DDTHH:MM:SS.ffffff". This format usually parses with
|
|
555
|
+
# `fromisoformat`, but not with Python 3.10
|
|
556
|
+
iso_format_regex = r"(?P<header>\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.)(?P<microseconds>\d{0,7})"
|
|
557
|
+
|
|
558
|
+
# In Python %f only supports exactly 6 digits so we need to adapt the string
|
|
559
|
+
# If microseconds has 7 digits, we remove the last one
|
|
560
|
+
# If microseconds has less than 6 digits, we pad it with 0
|
|
561
|
+
def adapt_microseconds(m: re.Match[str]) -> str:
|
|
562
|
+
microseconds = m.group("microseconds")
|
|
563
|
+
header_text = m.group("header")
|
|
564
|
+
|
|
565
|
+
if len(microseconds) == 7:
|
|
566
|
+
microseconds = microseconds[:-1]
|
|
567
|
+
|
|
568
|
+
return header_text + microseconds.ljust(6, "0")
|
|
569
|
+
|
|
570
|
+
if re.fullmatch(iso_format_regex, string):
|
|
571
|
+
adapted_string = re.sub(iso_format_regex, adapt_microseconds, string)
|
|
572
|
+
return datetime.strptime(adapted_string, "%Y-%m-%dT%H:%M:%S.%f")
|
|
573
|
+
|
|
574
|
+
raise ValueError("Unsupported format by Fable: %s" % (string))
|
|
575
|
+
|
|
576
|
+
|
|
577
|
+
def try_parse(string: str, def_value: FSharpRef[datetime]) -> bool:
|
|
578
|
+
try:
|
|
579
|
+
def_value.contents = parse(string)
|
|
580
|
+
return True
|
|
581
|
+
except Exception:
|
|
582
|
+
return False
|
|
583
|
+
|
|
584
|
+
|
|
585
|
+
def date(d: datetime) -> datetime:
|
|
586
|
+
return create(d.year, d.month, d.day, 0, 0, 0, 0, 0, kind(d))
|
|
587
|
+
|
|
588
|
+
|
|
589
|
+
def is_leap_year(year: int) -> bool:
|
|
590
|
+
return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)
|
|
591
|
+
|
|
592
|
+
|
|
593
|
+
def days_in_month(year: int, month: int) -> int:
|
|
594
|
+
if month == 2:
|
|
595
|
+
return 29 if is_leap_year(year) else 28
|
|
596
|
+
|
|
597
|
+
if month in (4, 6, 9, 11):
|
|
598
|
+
return 30
|
|
599
|
+
|
|
600
|
+
return 31
|
|
601
|
+
|
|
602
|
+
|
|
603
|
+
def add_years(d: datetime, v: int) -> datetime:
|
|
604
|
+
new_month = month(d)
|
|
605
|
+
new_year = year(d) + v
|
|
606
|
+
_days_in_month = days_in_month(new_year, new_month)
|
|
607
|
+
new_day = min(_days_in_month, day(d))
|
|
608
|
+
return create(new_year, new_month, new_day, hour(d), minute(d), second(d), millisecond(d), microsecond(d), kind(d))
|
|
609
|
+
|
|
610
|
+
|
|
611
|
+
def add_months(d: datetime, v: int) -> datetime:
|
|
612
|
+
new_month = month(d) + v
|
|
613
|
+
new_month_ = 0
|
|
614
|
+
year_offset = 0
|
|
615
|
+
if new_month > 12:
|
|
616
|
+
new_month_ = int(fmod(new_month, 12))
|
|
617
|
+
year_offset = new_month // 12
|
|
618
|
+
new_month = new_month_
|
|
619
|
+
elif new_month < 1:
|
|
620
|
+
new_month_ = 12 + int(fmod(new_month, 12))
|
|
621
|
+
year_offset = new_month // 12 + (-1 if new_month_ == 12 else 0)
|
|
622
|
+
new_month = new_month_
|
|
623
|
+
new_year = year(d) + year_offset
|
|
624
|
+
_days_in_month = days_in_month(new_year, new_month)
|
|
625
|
+
new_day = min(_days_in_month, day(d))
|
|
626
|
+
return create(new_year, new_month, new_day, hour(d), minute(d), second(d), millisecond(d), microsecond(d), kind(d))
|
|
627
|
+
|
|
628
|
+
|
|
629
|
+
def add_days(d: datetime, v: int) -> datetime:
|
|
630
|
+
return d + timedelta(days=v)
|
|
631
|
+
|
|
632
|
+
|
|
633
|
+
def add_hours(d: datetime, v: int) -> datetime:
|
|
634
|
+
return d + timedelta(hours=v)
|
|
635
|
+
|
|
636
|
+
|
|
637
|
+
def add_minutes(d: datetime, v: int) -> datetime:
|
|
638
|
+
return d + timedelta(minutes=v)
|
|
639
|
+
|
|
640
|
+
|
|
641
|
+
def add_seconds(d: datetime, v: int) -> datetime:
|
|
642
|
+
return d + timedelta(seconds=v)
|
|
643
|
+
|
|
644
|
+
|
|
645
|
+
def add_milliseconds(d: datetime, v: int) -> datetime:
|
|
646
|
+
return d + timedelta(milliseconds=v)
|
|
647
|
+
|
|
648
|
+
|
|
649
|
+
def add_microseconds(d: datetime, v: int) -> datetime:
|
|
650
|
+
return d + timedelta(microseconds=v)
|
|
651
|
+
|
|
652
|
+
|
|
653
|
+
def kind(d: datetime) -> DateKind:
|
|
654
|
+
if d.tzinfo == timezone.utc:
|
|
655
|
+
return DateKind.UTC
|
|
656
|
+
|
|
657
|
+
elif d.tzinfo is None:
|
|
658
|
+
return DateKind.Unspecified
|
|
659
|
+
|
|
660
|
+
# Should we check that tzinfo is local_time_zone?
|
|
661
|
+
return DateKind.Local
|
|
662
|
+
|
|
663
|
+
|
|
664
|
+
def specify_kind(d: datetime, kind: DateKind) -> datetime:
|
|
665
|
+
return create(year(d), month(d), day(d), hour(d), minute(d), second(d), millisecond(d), microsecond(d), kind)
|
|
666
|
+
|
|
667
|
+
|
|
668
|
+
def ticks(d: datetime) -> int:
|
|
669
|
+
# Note: It can happens that Ticks differs a little bit from the .NET implementation
|
|
670
|
+
# because of some rounding/precision issues in Python
|
|
671
|
+
# DateTime(1, 1, 1, 0, 0, 0, 0, 99, DateTimeKind.Utc).Ticks should be 990
|
|
672
|
+
# but Python returns 1040
|
|
673
|
+
# because d.timestamp():
|
|
674
|
+
# - returns -62135596799.9999
|
|
675
|
+
# - instead of -62135596800000
|
|
676
|
+
# compute timestamp in microseconds
|
|
677
|
+
return unix_epoch_microseconds_to_ticks(int(d.timestamp() * 1_000_000), date_offset(d) * 1_000)
|
|
678
|
+
|
|
679
|
+
|
|
680
|
+
def unix_epoch_microseconds_to_ticks(us: int, offset: int) -> int:
|
|
681
|
+
return int(((us + 62135596800000000) + offset) * 10)
|
|
682
|
+
|
|
683
|
+
|
|
684
|
+
def ticks_to_unix_epoch_microseconds(ticks: int) -> int:
|
|
685
|
+
return int((ticks - 621355968000000000) // 10)
|
|
686
|
+
|
|
687
|
+
|
|
688
|
+
def date_offset(d: datetime) -> int:
|
|
689
|
+
if d.tzinfo == timezone.utc:
|
|
690
|
+
return 0
|
|
691
|
+
else:
|
|
692
|
+
utc_offset = d.utcoffset()
|
|
693
|
+
|
|
694
|
+
# Is it correct to force an offset to local time
|
|
695
|
+
# for DateKind.Unspecified?
|
|
696
|
+
if utc_offset is None:
|
|
697
|
+
forced_utc_offset = d.astimezone().utcoffset()
|
|
698
|
+
assert forced_utc_offset is not None
|
|
699
|
+
return int(forced_utc_offset.total_seconds() * 1_000)
|
|
700
|
+
else:
|
|
701
|
+
return int(utc_offset.total_seconds() * 1_000)
|
|
702
|
+
|
|
703
|
+
# return 0 if d.tzinfo == timezone.utc else
|
|
704
|
+
|
|
705
|
+
|
|
706
|
+
def create_from_epoch_microseconds(us: int, kind: DateKind | None = None) -> datetime:
|
|
707
|
+
if kind == DateKind.UTC:
|
|
708
|
+
date = datetime.fromtimestamp(us / 1_000_000, timezone.utc)
|
|
709
|
+
else:
|
|
710
|
+
date = datetime.fromtimestamp(us / 1_000_000)
|
|
711
|
+
if kind == DateKind.Local:
|
|
712
|
+
date = date.astimezone()
|
|
713
|
+
|
|
714
|
+
return date
|
|
715
|
+
|
|
716
|
+
|
|
717
|
+
def from_ticks(ticks: int, kind: DateKind | None = None) -> datetime:
|
|
718
|
+
# Better default than Unspecified
|
|
719
|
+
kind = kind or DateKind.Local
|
|
720
|
+
date = create_from_epoch_microseconds(ticks_to_unix_epoch_microseconds(ticks), kind)
|
|
721
|
+
|
|
722
|
+
# Ticks are local to offset (in this case, either UTC or Local/Unknown).
|
|
723
|
+
# If kind is anything but UTC, that means that the tick number was not
|
|
724
|
+
# in utc, thus getTime() cannot return UTC, and needs to be shifted.
|
|
725
|
+
if kind != DateKind.UTC:
|
|
726
|
+
date = create_from_epoch_microseconds(int(date.timestamp() * 1_000_000 - date_offset(date) * 1_000), kind)
|
|
727
|
+
|
|
728
|
+
return date
|
|
729
|
+
|
|
730
|
+
|
|
731
|
+
__all__ = [
|
|
732
|
+
"subtract",
|
|
733
|
+
"op_subtraction",
|
|
734
|
+
"create",
|
|
735
|
+
"year",
|
|
736
|
+
"month",
|
|
737
|
+
"day",
|
|
738
|
+
"hour",
|
|
739
|
+
"minute",
|
|
740
|
+
"second",
|
|
741
|
+
"millisecond",
|
|
742
|
+
"microsecond",
|
|
743
|
+
"to_universal_time",
|
|
744
|
+
"day_of_week",
|
|
745
|
+
"day_of_year",
|
|
746
|
+
"to_short_date_string",
|
|
747
|
+
"to_long_date_string",
|
|
748
|
+
"to_short_time_string",
|
|
749
|
+
"to_long_time_string",
|
|
750
|
+
"to_string",
|
|
751
|
+
"now",
|
|
752
|
+
"utc_now",
|
|
753
|
+
"today",
|
|
754
|
+
"to_local_time",
|
|
755
|
+
"compare",
|
|
756
|
+
"equals",
|
|
757
|
+
"max_value",
|
|
758
|
+
"min_value",
|
|
759
|
+
"op_addition",
|
|
760
|
+
"add",
|
|
761
|
+
"parse",
|
|
762
|
+
"try_parse",
|
|
763
|
+
"date",
|
|
764
|
+
"is_leap_year",
|
|
765
|
+
"days_in_month",
|
|
766
|
+
"add_years",
|
|
767
|
+
"add_months",
|
|
768
|
+
"add_days",
|
|
769
|
+
"add_hours",
|
|
770
|
+
"add_minutes",
|
|
771
|
+
"add_seconds",
|
|
772
|
+
"add_milliseconds",
|
|
773
|
+
"add_microseconds",
|
|
774
|
+
"kind",
|
|
775
|
+
"specify_kind",
|
|
776
|
+
"ticks",
|
|
777
|
+
"date_offset",
|
|
778
|
+
"from_ticks",
|
|
779
|
+
]
|