numdaplot 0.1.0__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.
- numdaplot/__init__.py +506 -0
- numdaplot/arrays/__init__.py +5 -0
- numdaplot/arrays/array.py +92 -0
- numdaplot/arrays/array_arithmetic.py +404 -0
- numdaplot/arrays/array_calculation.py +143 -0
- numdaplot/arrays/array_conversion.py +150 -0
- numdaplot/arrays/array_creation.py +371 -0
- numdaplot/arrays/array_data.py +281 -0
- numdaplot/arrays/array_layout.py +179 -0
- numdaplot/arrays/array_logic.py +227 -0
- numdaplot/arrays/array_reflected_arithmetic.py +334 -0
- numdaplot/arrays/array_refusals.py +339 -0
- numdaplot/arrays/array_selection.py +195 -0
- numdaplot/arrays/array_sorting.py +59 -0
- numdaplot/arrays/axis_number.py +58 -0
- numdaplot/arrays/calculation/__init__.py +5 -0
- numdaplot/arrays/calculation/counting_statistics.py +325 -0
- numdaplot/arrays/calculation/location_statistics.py +268 -0
- numdaplot/arrays/calculation/math_function_values.py +183 -0
- numdaplot/arrays/calculation/statistic_values.py +209 -0
- numdaplot/arrays/calculation/time_function_values.py +419 -0
- numdaplot/arrays/conversion/__init__.py +5 -0
- numdaplot/arrays/conversion/array_text.py +62 -0
- numdaplot/arrays/conversion/equality_check.py +72 -0
- numdaplot/arrays/conversion/python_values.py +70 -0
- numdaplot/arrays/conversion/time_text.py +290 -0
- numdaplot/arrays/creation/__init__.py +5 -0
- numdaplot/arrays/creation/date_parts.py +89 -0
- numdaplot/arrays/creation/date_parts_values.py +437 -0
- numdaplot/arrays/creation/distribution.py +54 -0
- numdaplot/arrays/creation/filled_values.py +58 -0
- numdaplot/arrays/creation/list_conversion.py +311 -0
- numdaplot/arrays/creation/list_shape.py +97 -0
- numdaplot/arrays/creation/normal.py +65 -0
- numdaplot/arrays/creation/numpy_conversion.py +149 -0
- numdaplot/arrays/creation/random_integers.py +104 -0
- numdaplot/arrays/creation/random_values.py +97 -0
- numdaplot/arrays/creation/range_values.py +73 -0
- numdaplot/arrays/creation/spacing.py +84 -0
- numdaplot/arrays/creation/spacing_values.py +63 -0
- numdaplot/arrays/creation/uniform.py +63 -0
- numdaplot/arrays/equality.py +68 -0
- numdaplot/arrays/layout/__init__.py +5 -0
- numdaplot/arrays/layout/sorting_values.py +113 -0
- numdaplot/arrays/layout/unique_values.py +49 -0
- numdaplot/arrays/mapping/__init__.py +5 -0
- numdaplot/arrays/mapping/mapped_values.py +286 -0
- numdaplot/arrays/mapping/unmatched.py +50 -0
- numdaplot/arrays/mapping/value_change.py +55 -0
- numdaplot/arrays/mapping/value_mapping.py +161 -0
- numdaplot/arrays/math_functions/__init__.py +5 -0
- numdaplot/arrays/math_functions/absolute.py +27 -0
- numdaplot/arrays/math_functions/cosine.py +28 -0
- numdaplot/arrays/math_functions/exponential.py +27 -0
- numdaplot/arrays/math_functions/logarithm.py +72 -0
- numdaplot/arrays/math_functions/math_function.py +58 -0
- numdaplot/arrays/math_functions/round.py +58 -0
- numdaplot/arrays/math_functions/sine.py +28 -0
- numdaplot/arrays/math_functions/square_root.py +27 -0
- numdaplot/arrays/operations/__init__.py +5 -0
- numdaplot/arrays/operations/boolean_operands.py +48 -0
- numdaplot/arrays/operations/combination.py +157 -0
- numdaplot/arrays/operations/float_errors.py +170 -0
- numdaplot/arrays/operations/integer_bounds.py +175 -0
- numdaplot/arrays/operations/integer_rules.py +397 -0
- numdaplot/arrays/operations/operand.py +139 -0
- numdaplot/arrays/operations/time_arithmetic.py +479 -0
- numdaplot/arrays/operations/time_bounds.py +286 -0
- numdaplot/arrays/operations/time_result_bounds.py +397 -0
- numdaplot/arrays/operations/transformation.py +54 -0
- numdaplot/arrays/operations/type_requirements.py +94 -0
- numdaplot/arrays/replacement.py +66 -0
- numdaplot/arrays/selection/__init__.py +5 -0
- numdaplot/arrays/selection/comparison_masks.py +131 -0
- numdaplot/arrays/selection/membership_masks.py +118 -0
- numdaplot/arrays/selection/missing_mask.py +50 -0
- numdaplot/arrays/selection/region_index.py +178 -0
- numdaplot/arrays/selection/replaced_values.py +120 -0
- numdaplot/arrays/selection/rule_mask.py +83 -0
- numdaplot/arrays/selection/time_reference.py +172 -0
- numdaplot/arrays/shape.py +74 -0
- numdaplot/arrays/type_match.py +51 -0
- numdaplot/data_types/__init__.py +5 -0
- numdaplot/data_types/library.py +57 -0
- numdaplot/data_types/numpy_mapping.py +207 -0
- numdaplot/data_types/pandas_mapping.py +114 -0
- numdaplot/data_types/time_of_day.py +292 -0
- numdaplot/data_types/type.py +224 -0
- numdaplot/data_types/value_family.py +149 -0
- numdaplot/data_types/value_type.py +147 -0
- numdaplot/dates/__init__.py +5 -0
- numdaplot/dates/custom_date_format.py +83 -0
- numdaplot/dates/date_format.py +120 -0
- numdaplot/dates/date_part.py +59 -0
- numdaplot/dates/date_part_unit.py +153 -0
- numdaplot/dates/date_period.py +57 -0
- numdaplot/dates/duration_in.py +58 -0
- numdaplot/dates/duration_unit.py +90 -0
- numdaplot/dates/period_unit.py +101 -0
- numdaplot/dates/time_function.py +56 -0
- numdaplot/dates/time_zone.py +68 -0
- numdaplot/dates/time_zone_change.py +71 -0
- numdaplot/dates/time_zone_mode.py +81 -0
- numdaplot/dates/to_duration.py +58 -0
- numdaplot/errors/__init__.py +7 -0
- numdaplot/errors/broadcast_warning.py +36 -0
- numdaplot/errors/calculation_warning.py +35 -0
- numdaplot/errors/cell_out_of_range_error.py +77 -0
- numdaplot/errors/column_not_found_error.py +64 -0
- numdaplot/errors/conflicting_settings_error.py +60 -0
- numdaplot/errors/dimension_error.py +62 -0
- numdaplot/errors/display_warning.py +32 -0
- numdaplot/errors/duplicate_column_error.py +82 -0
- numdaplot/errors/duplicate_label_error.py +55 -0
- numdaplot/errors/duplicate_statistic_error.py +55 -0
- numdaplot/errors/duplicate_value_error.py +54 -0
- numdaplot/errors/empty_array_error.py +55 -0
- numdaplot/errors/empty_list_error.py +52 -0
- numdaplot/errors/empty_region_error.py +34 -0
- numdaplot/errors/empty_text_error.py +34 -0
- numdaplot/errors/empty_total_error.py +62 -0
- numdaplot/errors/empty_values_error.py +34 -0
- numdaplot/errors/file_access_error.py +70 -0
- numdaplot/errors/file_exists_error.py +62 -0
- numdaplot/errors/file_not_found_error.py +56 -0
- numdaplot/errors/incompatible_charts_error.py +80 -0
- numdaplot/errors/incompatible_types_error.py +104 -0
- numdaplot/errors/integer_overflow_error.py +61 -0
- numdaplot/errors/invalid_base_error.py +52 -0
- numdaplot/errors/invalid_bin_width_error.py +66 -0
- numdaplot/errors/invalid_bounds_error.py +58 -0
- numdaplot/errors/invalid_chart_data_error.py +81 -0
- numdaplot/errors/invalid_color_count_error.py +63 -0
- numdaplot/errors/invalid_color_error.py +51 -0
- numdaplot/errors/invalid_column_name_error.py +52 -0
- numdaplot/errors/invalid_conversion_error.py +119 -0
- numdaplot/errors/invalid_count_error.py +61 -0
- numdaplot/errors/invalid_date_format_error.py +51 -0
- numdaplot/errors/invalid_deviation_error.py +52 -0
- numdaplot/errors/invalid_fraction_error.py +51 -0
- numdaplot/errors/invalid_label_count_error.py +61 -0
- numdaplot/errors/invalid_limits_error.py +111 -0
- numdaplot/errors/invalid_opacity_error.py +52 -0
- numdaplot/errors/invalid_point_size_error.py +52 -0
- numdaplot/errors/invalid_position_error.py +106 -0
- numdaplot/errors/invalid_resolution_error.py +51 -0
- numdaplot/errors/invalid_rotation_error.py +53 -0
- numdaplot/errors/invalid_seed_error.py +53 -0
- numdaplot/errors/invalid_separator_error.py +52 -0
- numdaplot/errors/invalid_shape_error.py +52 -0
- numdaplot/errors/invalid_sheet_name_error.py +54 -0
- numdaplot/errors/invalid_size_error.py +58 -0
- numdaplot/errors/invalid_step_error.py +77 -0
- numdaplot/errors/invalid_suffixes_error.py +61 -0
- numdaplot/errors/invalid_time_zone_change_error.py +63 -0
- numdaplot/errors/invalid_type_error.py +79 -0
- numdaplot/errors/irregular_list_error.py +36 -0
- numdaplot/errors/join_relation_error.py +183 -0
- numdaplot/errors/missing_dependency_error.py +58 -0
- numdaplot/errors/missing_type_error.py +36 -0
- numdaplot/errors/missing_value_error.py +62 -0
- numdaplot/errors/not_single_value_error.py +53 -0
- numdaplot/errors/numdaplot_error.py +25 -0
- numdaplot/errors/numdaplot_warning.py +34 -0
- numdaplot/errors/occupied_cell_error.py +63 -0
- numdaplot/errors/out_of_domain_error.py +70 -0
- numdaplot/errors/readability_warning.py +35 -0
- numdaplot/errors/refused_operation_error.py +64 -0
- numdaplot/errors/refused_setting_error.py +60 -0
- numdaplot/errors/rejected_dates.py +60 -0
- numdaplot/errors/repeated_key.py +36 -0
- numdaplot/errors/shape_mismatch_error.py +67 -0
- numdaplot/errors/time_overflow_error.py +131 -0
- numdaplot/errors/time_zone_mismatch_error.py +83 -0
- numdaplot/errors/unknown_time_zone_error.py +51 -0
- numdaplot/errors/unmatched_value_error.py +81 -0
- numdaplot/errors/unsupported_image_format_error.py +56 -0
- numdaplot/errors/unsupported_index_error.py +38 -0
- numdaplot/errors/unsupported_missing_error.py +129 -0
- numdaplot/errors/unsupported_type_error.py +62 -0
- numdaplot/errors/value_conversion_error.py +215 -0
- numdaplot/ordering/__init__.py +5 -0
- numdaplot/ordering/missing_position.py +46 -0
- numdaplot/ordering/order.py +46 -0
- numdaplot/package_version.py +36 -0
- numdaplot/plots/__init__.py +5 -0
- numdaplot/plots/chart_layer.py +47 -0
- numdaplot/plots/charts/__init__.py +5 -0
- numdaplot/plots/charts/bar_chart.py +98 -0
- numdaplot/plots/charts/bar_layout.py +58 -0
- numdaplot/plots/charts/bin_count.py +61 -0
- numdaplot/plots/charts/bin_width.py +78 -0
- numdaplot/plots/charts/box_chart.py +97 -0
- numdaplot/plots/charts/cell_values.py +61 -0
- numdaplot/plots/charts/chart.py +59 -0
- numdaplot/plots/charts/chart_settings.py +105 -0
- numdaplot/plots/charts/color_scale.py +147 -0
- numdaplot/plots/charts/heatmap_chart.py +92 -0
- numdaplot/plots/charts/histogram_chart.py +93 -0
- numdaplot/plots/charts/line_chart.py +100 -0
- numdaplot/plots/charts/line_type.py +75 -0
- numdaplot/plots/charts/marker_shape.py +113 -0
- numdaplot/plots/charts/missing_chart.py +60 -0
- numdaplot/plots/charts/missing_map_chart.py +27 -0
- numdaplot/plots/charts/orientation.py +58 -0
- numdaplot/plots/charts/outliers.py +49 -0
- numdaplot/plots/charts/percentages.py +55 -0
- numdaplot/plots/charts/pie_chart.py +87 -0
- numdaplot/plots/charts/scatter_chart.py +159 -0
- numdaplot/plots/charts/value_axis.py +66 -0
- numdaplot/plots/data/__init__.py +5 -0
- numdaplot/plots/data/array_values.py +128 -0
- numdaplot/plots/data/chart_data.py +143 -0
- numdaplot/plots/data/chart_values.py +109 -0
- numdaplot/plots/data/column_reading.py +468 -0
- numdaplot/plots/data/heatmap_values.py +63 -0
- numdaplot/plots/data/missing_cells.py +165 -0
- numdaplot/plots/data/pie_values.py +215 -0
- numdaplot/plots/data/point_values.py +249 -0
- numdaplot/plots/data/position_kind.py +83 -0
- numdaplot/plots/data/renamed_layers.py +340 -0
- numdaplot/plots/data/sample_values.py +160 -0
- numdaplot/plots/data/shown_columns.py +248 -0
- numdaplot/plots/data/table_values.py +256 -0
- numdaplot/plots/data/unique_labels.py +45 -0
- numdaplot/plots/drawing/__init__.py +5 -0
- numdaplot/plots/drawing/bar_drawing.py +316 -0
- numdaplot/plots/drawing/box_drawing.py +344 -0
- numdaplot/plots/drawing/cell_merging.py +237 -0
- numdaplot/plots/drawing/chart_texts.py +124 -0
- numdaplot/plots/drawing/color_bar.py +57 -0
- numdaplot/plots/drawing/color_scale_values.py +120 -0
- numdaplot/plots/drawing/default_labels.py +41 -0
- numdaplot/plots/drawing/drawn_chart.py +50 -0
- numdaplot/plots/drawing/grid_axes.py +75 -0
- numdaplot/plots/drawing/heatmap_drawing.py +313 -0
- numdaplot/plots/drawing/histogram_drawing.py +350 -0
- numdaplot/plots/drawing/label_room.py +344 -0
- numdaplot/plots/drawing/label_thinning.py +216 -0
- numdaplot/plots/drawing/layer_alignment.py +319 -0
- numdaplot/plots/drawing/layer_colors.py +123 -0
- numdaplot/plots/drawing/line_drawing.py +85 -0
- numdaplot/plots/drawing/marker_codes.py +20 -0
- numdaplot/plots/drawing/missing_drawing.py +360 -0
- numdaplot/plots/drawing/moment_period_formatter.py +253 -0
- numdaplot/plots/drawing/pie_drawing.py +185 -0
- numdaplot/plots/drawing/plot_axes.py +38 -0
- numdaplot/plots/drawing/plot_drawing.py +288 -0
- numdaplot/plots/drawing/plot_theme.py +45 -0
- numdaplot/plots/drawing/position_axis.py +278 -0
- numdaplot/plots/drawing/scatter_drawing.py +364 -0
- numdaplot/plots/drawing/series_colors.py +177 -0
- numdaplot/plots/drawing/size_inches.py +45 -0
- numdaplot/plots/drawing/style_drawing.py +410 -0
- numdaplot/plots/drawing/text_contrast.py +44 -0
- numdaplot/plots/drawing/tick_rotation.py +354 -0
- numdaplot/plots/drawing/time_axis.py +212 -0
- numdaplot/plots/drawing/whole_numbers.py +72 -0
- numdaplot/plots/figure/__init__.py +5 -0
- numdaplot/plots/figure/cell.py +95 -0
- numdaplot/plots/figure/figure.py +256 -0
- numdaplot/plots/figure/figure_drawing.py +99 -0
- numdaplot/plots/figure/figure_style.py +60 -0
- numdaplot/plots/figure/layout.py +71 -0
- numdaplot/plots/figure/placement.py +150 -0
- numdaplot/plots/layer_reading.py +166 -0
- numdaplot/plots/output/__init__.py +5 -0
- numdaplot/plots/output/image_saving.py +187 -0
- numdaplot/plots/output/plot_display.py +181 -0
- numdaplot/plots/output/shown_object.py +45 -0
- numdaplot/plots/overlay_checks.py +245 -0
- numdaplot/plots/plot.py +31 -0
- numdaplot/plots/plot_data.py +140 -0
- numdaplot/plots/plot_distribution_creation.py +237 -0
- numdaplot/plots/plot_output.py +124 -0
- numdaplot/plots/plot_overlays.py +273 -0
- numdaplot/plots/plot_overview_creation.py +195 -0
- numdaplot/plots/plot_series_creation.py +213 -0
- numdaplot/plots/style/__init__.py +5 -0
- numdaplot/plots/style/axis_settings.py +60 -0
- numdaplot/plots/style/color.py +168 -0
- numdaplot/plots/style/custom_color.py +65 -0
- numdaplot/plots/style/grid_lines.py +49 -0
- numdaplot/plots/style/image_options.py +71 -0
- numdaplot/plots/style/legend_position.py +149 -0
- numdaplot/plots/style/plot_style.py +136 -0
- numdaplot/plots/style/size.py +70 -0
- numdaplot/plots/style/size_unit.py +62 -0
- numdaplot/positions/__init__.py +5 -0
- numdaplot/positions/axis.py +54 -0
- numdaplot/positions/index.py +51 -0
- numdaplot/positions/range.py +90 -0
- numdaplot/positions/region.py +92 -0
- numdaplot/py.typed +0 -0
- numdaplot/ratios/__init__.py +5 -0
- numdaplot/ratios/fraction.py +40 -0
- numdaplot/ratios/measure.py +48 -0
- numdaplot/rules/__init__.py +5 -0
- numdaplot/rules/between.py +78 -0
- numdaplot/rules/bounds.py +83 -0
- numdaplot/rules/case.py +48 -0
- numdaplot/rules/contains.py +63 -0
- numdaplot/rules/equal.py +43 -0
- numdaplot/rules/greater.py +39 -0
- numdaplot/rules/greater_or_equal.py +38 -0
- numdaplot/rules/is_in.py +67 -0
- numdaplot/rules/is_missing.py +25 -0
- numdaplot/rules/is_present.py +25 -0
- numdaplot/rules/less.py +39 -0
- numdaplot/rules/less_or_equal.py +38 -0
- numdaplot/rules/not_equal.py +45 -0
- numdaplot/rules/rule.py +62 -0
- numdaplot/rules/rule_values.py +44 -0
- numdaplot/rules/value_rule.py +110 -0
- numdaplot/settings/__init__.py +5 -0
- numdaplot/settings/argument_types.py +327 -0
- numdaplot/settings/field_types.py +593 -0
- numdaplot/statistics/__init__.py +5 -0
- numdaplot/statistics/count.py +71 -0
- numdaplot/statistics/count_distinct.py +27 -0
- numdaplot/statistics/counted_missing.py +46 -0
- numdaplot/statistics/maximum.py +27 -0
- numdaplot/statistics/mean.py +27 -0
- numdaplot/statistics/median.py +27 -0
- numdaplot/statistics/minimum.py +27 -0
- numdaplot/statistics/most_frequent.py +27 -0
- numdaplot/statistics/most_frequent_count.py +27 -0
- numdaplot/statistics/quantile.py +61 -0
- numdaplot/statistics/standard_deviation.py +29 -0
- numdaplot/statistics/statistic.py +63 -0
- numdaplot/statistics/sum.py +27 -0
- numdaplot/tables/__init__.py +5 -0
- numdaplot/tables/aggregation/__init__.py +5 -0
- numdaplot/tables/aggregation/aggregated_frame.py +189 -0
- numdaplot/tables/aggregation/aggregation.py +97 -0
- numdaplot/tables/aggregation/calculation.py +123 -0
- numdaplot/tables/aggregation/result_column.py +108 -0
- numdaplot/tables/aggregation/row_groups.py +96 -0
- numdaplot/tables/aggregation/statistic_name.py +122 -0
- numdaplot/tables/columns/__init__.py +5 -0
- numdaplot/tables/columns/added_column.py +89 -0
- numdaplot/tables/columns/boolean_conversion.py +144 -0
- numdaplot/tables/columns/boolean_rule.py +59 -0
- numdaplot/tables/columns/bracket_end.py +50 -0
- numdaplot/tables/columns/bracket_names.py +346 -0
- numdaplot/tables/columns/bracketed_column.py +179 -0
- numdaplot/tables/columns/brackets.py +234 -0
- numdaplot/tables/columns/chosen_columns.py +55 -0
- numdaplot/tables/columns/column_choice.py +84 -0
- numdaplot/tables/columns/column_mode.py +64 -0
- numdaplot/tables/columns/column_names.py +186 -0
- numdaplot/tables/columns/conversion.py +103 -0
- numdaplot/tables/columns/converted_column.py +669 -0
- numdaplot/tables/columns/date_conversion.py +526 -0
- numdaplot/tables/columns/date_range.py +135 -0
- numdaplot/tables/columns/name_change.py +67 -0
- numdaplot/tables/columns/new_column.py +79 -0
- numdaplot/tables/columns/number_conversion.py +281 -0
- numdaplot/tables/columns/renamed_columns.py +60 -0
- numdaplot/tables/columns/renaming.py +81 -0
- numdaplot/tables/columns/text_conversion.py +70 -0
- numdaplot/tables/columns/time_conversion.py +313 -0
- numdaplot/tables/columns/time_zone_conversion.py +128 -0
- numdaplot/tables/conflict.py +68 -0
- numdaplot/tables/description/__init__.py +5 -0
- numdaplot/tables/description/described_frame.py +335 -0
- numdaplot/tables/description/description.py +155 -0
- numdaplot/tables/duplicates/__init__.py +5 -0
- numdaplot/tables/duplicates/deduplicated_frame.py +66 -0
- numdaplot/tables/duplicates/deduplication.py +88 -0
- numdaplot/tables/duplicates/keep.py +81 -0
- numdaplot/tables/files/__init__.py +5 -0
- numdaplot/tables/files/column_names.py +60 -0
- numdaplot/tables/files/csv_file.py +265 -0
- numdaplot/tables/files/csv_read_options.py +89 -0
- numdaplot/tables/files/csv_separator.py +41 -0
- numdaplot/tables/files/csv_write_options.py +79 -0
- numdaplot/tables/files/decimal_count.py +42 -0
- numdaplot/tables/files/encoding.py +82 -0
- numdaplot/tables/files/excel_file.py +171 -0
- numdaplot/tables/files/excel_read_options.py +79 -0
- numdaplot/tables/files/excel_sheet.py +50 -0
- numdaplot/tables/files/excel_time_cells.py +146 -0
- numdaplot/tables/files/excel_write_options.py +63 -0
- numdaplot/tables/files/file_access.py +152 -0
- numdaplot/tables/files/file_paths.py +106 -0
- numdaplot/tables/files/json_decimals.py +387 -0
- numdaplot/tables/files/json_file.py +203 -0
- numdaplot/tables/files/json_layout.py +63 -0
- numdaplot/tables/files/json_read_options.py +64 -0
- numdaplot/tables/files/json_write_options.py +71 -0
- numdaplot/tables/files/missing_texts.py +63 -0
- numdaplot/tables/files/optional_package.py +42 -0
- numdaplot/tables/files/pandas_backend.py +11 -0
- numdaplot/tables/files/parquet_file.py +91 -0
- numdaplot/tables/files/parquet_read_options.py +56 -0
- numdaplot/tables/files/sas_file.py +94 -0
- numdaplot/tables/files/sas_read_options.py +67 -0
- numdaplot/tables/files/stata_file.py +83 -0
- numdaplot/tables/files/stata_read_options.py +56 -0
- numdaplot/tables/files/xpt_read_options.py +65 -0
- numdaplot/tables/filtering/__init__.py +5 -0
- numdaplot/tables/filtering/checked_frame.py +60 -0
- numdaplot/tables/filtering/column_mask.py +71 -0
- numdaplot/tables/filtering/column_match.py +62 -0
- numdaplot/tables/filtering/condition.py +94 -0
- numdaplot/tables/filtering/filter.py +74 -0
- numdaplot/tables/filtering/filter_mode.py +67 -0
- numdaplot/tables/filtering/row_mask.py +152 -0
- numdaplot/tables/filtering/rule_moments.py +164 -0
- numdaplot/tables/frames/__init__.py +5 -0
- numdaplot/tables/frames/array_frame.py +95 -0
- numdaplot/tables/frames/cleaned_names.py +132 -0
- numdaplot/tables/frames/column.py +15 -0
- numdaplot/tables/frames/column_values.py +273 -0
- numdaplot/tables/frames/frame_equality.py +130 -0
- numdaplot/tables/frames/frame_normalization.py +459 -0
- numdaplot/tables/frames/named_column_errors.py +85 -0
- numdaplot/tables/frames/pandas_decimals.py +113 -0
- numdaplot/tables/frames/region_positions.py +113 -0
- numdaplot/tables/frames/table_text.py +222 -0
- numdaplot/tables/frames/time_columns.py +345 -0
- numdaplot/tables/frames/time_range_errors.py +117 -0
- numdaplot/tables/frames/time_zones.py +271 -0
- numdaplot/tables/joining/__init__.py +5 -0
- numdaplot/tables/joining/join.py +110 -0
- numdaplot/tables/joining/join_keys.py +367 -0
- numdaplot/tables/joining/join_mode.py +93 -0
- numdaplot/tables/joining/join_relation.py +149 -0
- numdaplot/tables/joining/join_suffixes.py +71 -0
- numdaplot/tables/joining/joined_frame.py +166 -0
- numdaplot/tables/joining/joined_names.py +107 -0
- numdaplot/tables/joining/joined_rows.py +235 -0
- numdaplot/tables/joining/key_types.py +57 -0
- numdaplot/tables/joining/relation.py +78 -0
- numdaplot/tables/missing/__init__.py +5 -0
- numdaplot/tables/missing/missing_count.py +59 -0
- numdaplot/tables/missing/missing_counts.py +214 -0
- numdaplot/tables/missing/missing_drop.py +98 -0
- numdaplot/tables/missing/missing_mode.py +63 -0
- numdaplot/tables/missing/missing_ratio.py +71 -0
- numdaplot/tables/missing/missing_removal.py +257 -0
- numdaplot/tables/missing/missing_summary.py +174 -0
- numdaplot/tables/missing/ratio_comparison.py +70 -0
- numdaplot/tables/pivot/__init__.py +5 -0
- numdaplot/tables/pivot/pivot_table.py +104 -0
- numdaplot/tables/pivot/pivoted_frame.py +244 -0
- numdaplot/tables/preview/__init__.py +5 -0
- numdaplot/tables/preview/notebook_display.py +238 -0
- numdaplot/tables/preview/preview.py +100 -0
- numdaplot/tables/preview/preview_rows.py +55 -0
- numdaplot/tables/preview/shown_columns.py +62 -0
- numdaplot/tables/preview/side.py +82 -0
- numdaplot/tables/sorting/__init__.py +5 -0
- numdaplot/tables/sorting/sort_key.py +71 -0
- numdaplot/tables/sorting/sorted_frame.py +81 -0
- numdaplot/tables/sorting/sorting.py +82 -0
- numdaplot/tables/table.py +71 -0
- numdaplot/tables/table_calculation.py +172 -0
- numdaplot/tables/table_columns.py +214 -0
- numdaplot/tables/table_conversion.py +351 -0
- numdaplot/tables/table_data.py +321 -0
- numdaplot/tables/table_display.py +56 -0
- numdaplot/tables/table_joining.py +80 -0
- numdaplot/tables/table_layout.py +105 -0
- numdaplot/tables/table_missing.py +146 -0
- numdaplot/tables/table_reading.py +451 -0
- numdaplot/tables/table_refusals.py +295 -0
- numdaplot/tables/table_selection.py +163 -0
- numdaplot/tables/table_writing.py +269 -0
- numdaplot-0.1.0.dist-info/METADATA +176 -0
- numdaplot-0.1.0.dist-info/RECORD +474 -0
- numdaplot-0.1.0.dist-info/WHEEL +4 -0
- numdaplot-0.1.0.dist-info/licenses/LICENSE +28 -0
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Writing of a Table in a file.
|
|
3
|
+
|
|
4
|
+
.. versionadded:: 0.1.0
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
from numdaplot.settings.argument_types import checked_arguments
|
|
10
|
+
from numdaplot.tables.conflict import Conflict
|
|
11
|
+
from numdaplot.tables.files.csv_file import write_csv_file
|
|
12
|
+
from numdaplot.tables.files.csv_write_options import CsvWriteOptions
|
|
13
|
+
from numdaplot.tables.files.excel_file import write_excel_file
|
|
14
|
+
from numdaplot.tables.files.excel_write_options import ExcelWriteOptions
|
|
15
|
+
from numdaplot.tables.files.file_access import WRITE_OPERATION, FileAccessErrors
|
|
16
|
+
from numdaplot.tables.files.file_paths import FilePath, require_free_path
|
|
17
|
+
from numdaplot.tables.files.json_file import write_json_file
|
|
18
|
+
from numdaplot.tables.files.json_write_options import JsonWriteOptions
|
|
19
|
+
from numdaplot.tables.files.parquet_file import write_parquet_file
|
|
20
|
+
from numdaplot.tables.files.stata_file import write_stata_file
|
|
21
|
+
from numdaplot.tables.frames.time_columns import read_time_objects_frame, write_time_texts_frame
|
|
22
|
+
from numdaplot.tables.table_data import TableData
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class TableWriting(TableData):
|
|
26
|
+
"""
|
|
27
|
+
Writing of a Table in a CSV, JSON, Excel, Parquet or Stata file.
|
|
28
|
+
|
|
29
|
+
An existing file is never overwritten unless ``on_conflict`` is ``Conflict.REPLACE``.
|
|
30
|
+
|
|
31
|
+
.. versionadded:: 0.1.0
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
@checked_arguments
|
|
35
|
+
def to_csv(
|
|
36
|
+
self, path: FilePath, options: CsvWriteOptions | None = None, on_conflict: Conflict = Conflict.ERROR
|
|
37
|
+
) -> None:
|
|
38
|
+
"""
|
|
39
|
+
Write the Table in a CSV file, column names on the first row, without row numbers.
|
|
40
|
+
|
|
41
|
+
Missing values are written as empty values, and times of day as texts such as ``15:35:00``.
|
|
42
|
+
|
|
43
|
+
.. versionadded:: 0.1.0
|
|
44
|
+
|
|
45
|
+
Parameters
|
|
46
|
+
----------
|
|
47
|
+
path
|
|
48
|
+
The path of the file, a ``FilePath`` such as ``"sales.csv"`` or ``Path("data/sales.csv")``.
|
|
49
|
+
options
|
|
50
|
+
The separator and the encoding, ``","`` and UTF-8 when omitted.
|
|
51
|
+
on_conflict
|
|
52
|
+
``ERROR`` by default, refusing to overwrite an existing file, or ``REPLACE`` to overwrite it.
|
|
53
|
+
|
|
54
|
+
Raises
|
|
55
|
+
------
|
|
56
|
+
InvalidTypeError
|
|
57
|
+
When an argument is not of the type its annotation names.
|
|
58
|
+
FileExistsError
|
|
59
|
+
When a file exists at the path and ``on_conflict`` is ``ERROR``.
|
|
60
|
+
FileAccessError
|
|
61
|
+
When the file system refuses the file: missing folder, missing permission and so on.
|
|
62
|
+
|
|
63
|
+
Examples
|
|
64
|
+
--------
|
|
65
|
+
>>> import tempfile
|
|
66
|
+
>>> from pathlib import Path
|
|
67
|
+
>>> import numdaplot as ndp
|
|
68
|
+
>>> path = Path(tempfile.mkdtemp()) / "sales.csv"
|
|
69
|
+
>>> table = ndp.Table.from_arrays({"price": ndp.Array.from_list([1.5, 8.0])})
|
|
70
|
+
>>> table.to_csv(path, ndp.CsvWriteOptions(separator=";"))
|
|
71
|
+
>>> print(path.read_text())
|
|
72
|
+
price
|
|
73
|
+
1.5
|
|
74
|
+
8.0
|
|
75
|
+
<BLANKLINE>
|
|
76
|
+
"""
|
|
77
|
+
file_path = Path(path)
|
|
78
|
+
require_free_path(file_path, on_conflict)
|
|
79
|
+
if options is None:
|
|
80
|
+
options = CsvWriteOptions()
|
|
81
|
+
|
|
82
|
+
with FileAccessErrors(WRITE_OPERATION, file_path):
|
|
83
|
+
write_csv_file(write_time_texts_frame(self._frame), file_path, options)
|
|
84
|
+
|
|
85
|
+
@checked_arguments
|
|
86
|
+
def to_json(
|
|
87
|
+
self, path: FilePath, options: JsonWriteOptions | None = None, on_conflict: Conflict = Conflict.ERROR
|
|
88
|
+
) -> None:
|
|
89
|
+
"""
|
|
90
|
+
Write the Table in a JSON file in UTF-8, one object per row.
|
|
91
|
+
|
|
92
|
+
Missing values are written as ``null``, dates and durations in the ISO 8601 format, times of day as texts such
|
|
93
|
+
as ``15:35:00``, and decimals with every digit of their value unless ``options`` gives their number.
|
|
94
|
+
|
|
95
|
+
.. versionadded:: 0.1.0
|
|
96
|
+
|
|
97
|
+
Parameters
|
|
98
|
+
----------
|
|
99
|
+
path
|
|
100
|
+
The path of the file, a ``FilePath`` such as ``"sales.json"`` or ``Path("data/sales.json")``.
|
|
101
|
+
options
|
|
102
|
+
The layout of the rows and the number of decimals, one list of objects with every digit when omitted.
|
|
103
|
+
on_conflict
|
|
104
|
+
``ERROR`` by default, refusing to overwrite an existing file, or ``REPLACE`` to overwrite it.
|
|
105
|
+
|
|
106
|
+
Raises
|
|
107
|
+
------
|
|
108
|
+
InvalidTypeError
|
|
109
|
+
When an argument is not of the type its annotation names.
|
|
110
|
+
FileExistsError
|
|
111
|
+
When a file exists at the path and ``on_conflict`` is ``ERROR``.
|
|
112
|
+
FileAccessError
|
|
113
|
+
When the file system refuses the file: missing folder, missing permission and so on.
|
|
114
|
+
ValueConversionError
|
|
115
|
+
At the first infinite value of a decimal column, which JSON cannot write: replace it first.
|
|
116
|
+
|
|
117
|
+
Examples
|
|
118
|
+
--------
|
|
119
|
+
>>> import tempfile
|
|
120
|
+
>>> from pathlib import Path
|
|
121
|
+
>>> import numdaplot as ndp
|
|
122
|
+
>>> path = Path(tempfile.mkdtemp()) / "sales.json"
|
|
123
|
+
>>> ndp.Table.from_arrays({"city": ndp.Array.from_list(["Paris"])}).to_json(path)
|
|
124
|
+
>>> path.read_text()
|
|
125
|
+
'[{"city":"Paris"}]'
|
|
126
|
+
"""
|
|
127
|
+
file_path = Path(path)
|
|
128
|
+
require_free_path(file_path, on_conflict)
|
|
129
|
+
if options is None:
|
|
130
|
+
options = JsonWriteOptions()
|
|
131
|
+
|
|
132
|
+
with FileAccessErrors(WRITE_OPERATION, file_path):
|
|
133
|
+
write_json_file(write_time_texts_frame(self._frame), file_path, options)
|
|
134
|
+
|
|
135
|
+
@checked_arguments
|
|
136
|
+
def to_excel(
|
|
137
|
+
self, path: FilePath, options: ExcelWriteOptions | None = None, on_conflict: Conflict = Conflict.ERROR
|
|
138
|
+
) -> None:
|
|
139
|
+
"""
|
|
140
|
+
Write the Table in a sheet of an Excel file, column names on the first row.
|
|
141
|
+
|
|
142
|
+
Times of day are written as texts such as ``15:35:00``. Needs the ``excel`` extra:
|
|
143
|
+
``pip install numdaplot[excel]``.
|
|
144
|
+
|
|
145
|
+
.. versionadded:: 0.1.0
|
|
146
|
+
|
|
147
|
+
Parameters
|
|
148
|
+
----------
|
|
149
|
+
path
|
|
150
|
+
The path of the file, a ``FilePath`` such as ``"sales.xlsx"`` or ``Path("data/sales.xlsx")``.
|
|
151
|
+
options
|
|
152
|
+
The name of the sheet, ``"Sheet1"`` when omitted.
|
|
153
|
+
on_conflict
|
|
154
|
+
``ERROR`` by default, refusing to overwrite an existing file, or ``REPLACE`` to overwrite it.
|
|
155
|
+
|
|
156
|
+
Raises
|
|
157
|
+
------
|
|
158
|
+
InvalidTypeError
|
|
159
|
+
When an argument is not of the type its annotation names.
|
|
160
|
+
FileExistsError
|
|
161
|
+
When a file exists at the path and ``on_conflict`` is ``ERROR``.
|
|
162
|
+
FileAccessError
|
|
163
|
+
When the file system refuses the file: missing folder, missing permission and so on.
|
|
164
|
+
MissingDependencyError
|
|
165
|
+
When the ``excel`` extra is not installed.
|
|
166
|
+
|
|
167
|
+
Examples
|
|
168
|
+
--------
|
|
169
|
+
>>> import tempfile
|
|
170
|
+
>>> from pathlib import Path
|
|
171
|
+
>>> import numdaplot as ndp
|
|
172
|
+
>>> path = Path(tempfile.mkdtemp()) / "sales.xlsx"
|
|
173
|
+
>>> table = ndp.Table.from_arrays({"price": ndp.Array.from_list([1.5])})
|
|
174
|
+
>>> table.to_excel(path, ndp.ExcelWriteOptions(sheet="Sales"))
|
|
175
|
+
>>> ndp.Table.from_excel(path, ndp.ExcelReadOptions(sheet="Sales")).row_count
|
|
176
|
+
1
|
|
177
|
+
"""
|
|
178
|
+
file_path = Path(path)
|
|
179
|
+
require_free_path(file_path, on_conflict)
|
|
180
|
+
if options is None:
|
|
181
|
+
options = ExcelWriteOptions()
|
|
182
|
+
|
|
183
|
+
with FileAccessErrors(WRITE_OPERATION, file_path):
|
|
184
|
+
write_excel_file(write_time_texts_frame(self._frame), file_path, options)
|
|
185
|
+
|
|
186
|
+
@checked_arguments
|
|
187
|
+
def to_parquet(self, path: FilePath, on_conflict: Conflict = Conflict.ERROR) -> None:
|
|
188
|
+
"""
|
|
189
|
+
Write the Table in a Parquet file, which keeps the type of each column.
|
|
190
|
+
|
|
191
|
+
Times of day are stored as Parquet times, read back as ``TIME``. Needs the ``parquet`` extra:
|
|
192
|
+
``pip install numdaplot[parquet]``.
|
|
193
|
+
|
|
194
|
+
.. versionadded:: 0.1.0
|
|
195
|
+
|
|
196
|
+
Parameters
|
|
197
|
+
----------
|
|
198
|
+
path
|
|
199
|
+
The path of the file, a ``FilePath`` such as ``"sales.parquet"`` or ``Path("data/sales.parquet")``.
|
|
200
|
+
on_conflict
|
|
201
|
+
``ERROR`` by default, refusing to overwrite an existing file, or ``REPLACE`` to overwrite it.
|
|
202
|
+
|
|
203
|
+
Raises
|
|
204
|
+
------
|
|
205
|
+
InvalidTypeError
|
|
206
|
+
When an argument is not of the type its annotation names.
|
|
207
|
+
FileExistsError
|
|
208
|
+
When a file exists at the path and ``on_conflict`` is ``ERROR``.
|
|
209
|
+
FileAccessError
|
|
210
|
+
When the file system refuses the file: missing folder, missing permission and so on.
|
|
211
|
+
MissingDependencyError
|
|
212
|
+
When the ``parquet`` extra is not installed.
|
|
213
|
+
|
|
214
|
+
Examples
|
|
215
|
+
--------
|
|
216
|
+
>>> import tempfile
|
|
217
|
+
>>> from pathlib import Path
|
|
218
|
+
>>> import numdaplot as ndp
|
|
219
|
+
>>> path = Path(tempfile.mkdtemp()) / "sales.parquet"
|
|
220
|
+
>>> ndp.Table.from_arrays({"count": ndp.Array.from_list([3])}).to_parquet(path)
|
|
221
|
+
>>> path.exists()
|
|
222
|
+
True
|
|
223
|
+
"""
|
|
224
|
+
file_path = Path(path)
|
|
225
|
+
require_free_path(file_path, on_conflict)
|
|
226
|
+
with FileAccessErrors(WRITE_OPERATION, file_path):
|
|
227
|
+
write_parquet_file(read_time_objects_frame(self._frame), file_path)
|
|
228
|
+
|
|
229
|
+
@checked_arguments
|
|
230
|
+
def to_stata(self, path: FilePath, on_conflict: Conflict = Conflict.ERROR) -> None:
|
|
231
|
+
"""
|
|
232
|
+
Write the Table in a Stata file (``.dta``).
|
|
233
|
+
|
|
234
|
+
Stata stores integers and booleans holding missing values as decimals, a missing text as an empty text, and
|
|
235
|
+
times of day as texts such as ``15:35:00``, as it has no type for them. Column names that Stata refuses, such
|
|
236
|
+
as names with spaces, are changed by pandas with a warning.
|
|
237
|
+
|
|
238
|
+
.. versionadded:: 0.1.0
|
|
239
|
+
|
|
240
|
+
Parameters
|
|
241
|
+
----------
|
|
242
|
+
path
|
|
243
|
+
The path of the file, a ``FilePath`` such as ``"sales.dta"`` or ``Path("data/sales.dta")``.
|
|
244
|
+
on_conflict
|
|
245
|
+
``ERROR`` by default, refusing to overwrite an existing file, or ``REPLACE`` to overwrite it.
|
|
246
|
+
|
|
247
|
+
Raises
|
|
248
|
+
------
|
|
249
|
+
InvalidTypeError
|
|
250
|
+
When an argument is not of the type its annotation names.
|
|
251
|
+
FileExistsError
|
|
252
|
+
When a file exists at the path and ``on_conflict`` is ``ERROR``.
|
|
253
|
+
FileAccessError
|
|
254
|
+
When the file system refuses the file: missing folder, missing permission and so on.
|
|
255
|
+
|
|
256
|
+
Examples
|
|
257
|
+
--------
|
|
258
|
+
>>> import tempfile
|
|
259
|
+
>>> from pathlib import Path
|
|
260
|
+
>>> import numdaplot as ndp
|
|
261
|
+
>>> path = Path(tempfile.mkdtemp()) / "sales.dta"
|
|
262
|
+
>>> ndp.Table.from_arrays({"price": ndp.Array.from_list([1.5])}).to_stata(path)
|
|
263
|
+
>>> path.exists()
|
|
264
|
+
True
|
|
265
|
+
"""
|
|
266
|
+
file_path = Path(path)
|
|
267
|
+
require_free_path(file_path, on_conflict)
|
|
268
|
+
with FileAccessErrors(WRITE_OPERATION, file_path):
|
|
269
|
+
write_stata_file(write_time_texts_frame(self._frame), file_path)
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: numdaplot
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A simpler, explicit API over numpy, pandas and matplotlib.
|
|
5
|
+
Project-URL: Repository, https://github.com/Ryieru/numdaplot
|
|
6
|
+
Project-URL: Documentation, https://ryieru.github.io/numdaplot/
|
|
7
|
+
Author: Ryieru
|
|
8
|
+
License-Expression: BSD-3-Clause
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Science/Research
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
15
|
+
Classifier: Topic :: Scientific/Engineering
|
|
16
|
+
Classifier: Typing :: Typed
|
|
17
|
+
Requires-Python: >=3.13
|
|
18
|
+
Requires-Dist: matplotlib<4,>=3.10.7
|
|
19
|
+
Requires-Dist: numpy<3,>=2.2
|
|
20
|
+
Requires-Dist: pandas<4,>=2.3
|
|
21
|
+
Provides-Extra: excel
|
|
22
|
+
Requires-Dist: openpyxl<4,>=3.1.3; extra == 'excel'
|
|
23
|
+
Provides-Extra: parquet
|
|
24
|
+
Requires-Dist: pyarrow>=18.1; extra == 'parquet'
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
|
|
27
|
+
# numdaplot
|
|
28
|
+
|
|
29
|
+
A simpler, explicit API over numpy, pandas and matplotlib.
|
|
30
|
+
|
|
31
|
+
Each action has exactly one way to be written, settings are typed objects that check their values
|
|
32
|
+
when they are created, and every operation returns a new object.
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
import numdaplot as ndp
|
|
36
|
+
|
|
37
|
+
prices = ndp.Array.from_list([12.5, 8.0, None, 30.0])
|
|
38
|
+
taxed_prices = prices * 1.2
|
|
39
|
+
high_prices = taxed_prices.select(ndp.Greater(10))
|
|
40
|
+
mean_price = prices.compute(ndp.Mean()).to_value()
|
|
41
|
+
|
|
42
|
+
sales = ndp.Table.from_csv("sales.csv")
|
|
43
|
+
expensive = ndp.Condition(rule=ndp.Greater(100), columns=["price"])
|
|
44
|
+
expensive_sales = sales.filter(ndp.Filter(conditions=[expensive]))
|
|
45
|
+
average_price = ndp.Calculation(column="price", function=ndp.Mean())
|
|
46
|
+
by_city = expensive_sales.aggregate(ndp.Aggregation(calculations=[average_price], group_by=["city"]))
|
|
47
|
+
|
|
48
|
+
chart = ndp.BarChart(x="city", y=["price_mean"])
|
|
49
|
+
style = ndp.PlotStyle(title="Average price per city")
|
|
50
|
+
plot = ndp.Plot.bar(by_city, chart, style)
|
|
51
|
+
plot.save("prices.png")
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Status
|
|
55
|
+
|
|
56
|
+
numdaplot is in alpha: the API can still change between versions, and `ndp.__version__` gives the installed version.
|
|
57
|
+
The shared foundations (types, rules, statistics, positions,
|
|
58
|
+
sort settings, errors), `Array`, `Table`, the tools for missing values and dates (formats, time zones,
|
|
59
|
+
parts, periods and durations), line, bar, scatter, histogram, box, pie, heatmap and missing value plots,
|
|
60
|
+
charts overlaid on a plot, and figures placing plots on a grid are available.
|
|
61
|
+
|
|
62
|
+
## Requirements
|
|
63
|
+
|
|
64
|
+
- Python 3.13 or later
|
|
65
|
+
- numpy 2.2+, pandas 2.3+ and matplotlib 3.10.7+
|
|
66
|
+
- Optional extras: `excel` (openpyxl) and `parquet` (pyarrow)
|
|
67
|
+
|
|
68
|
+
## Installation
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
pip install numdaplot
|
|
72
|
+
pip install "numdaplot[excel,parquet]"
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
The `excel` extra reads and writes Excel files, the `parquet` extra reads and writes Parquet files.
|
|
76
|
+
|
|
77
|
+
## Development
|
|
78
|
+
|
|
79
|
+
From a clone of the repository, with [uv](https://docs.astral.sh/uv/):
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
uv sync --all-extras
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The extras are needed to run every test, since the Excel and Parquet tests write real files.
|
|
86
|
+
|
|
87
|
+
## Run the tests
|
|
88
|
+
|
|
89
|
+
The test entry point runs the unit tests, the functional tests and every docstring example:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
uv run python run_tests.py
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Arguments are passed to pytest, for example `uv run python run_tests.py -k between`.
|
|
96
|
+
|
|
97
|
+
## Measure the coverage
|
|
98
|
+
|
|
99
|
+
The coverage of every line and every branch of `src/numdaplot` and `tools/docs` is measured while the whole suite
|
|
100
|
+
runs, and must reach 99.50%:
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
uv run coverage run run_tests.py
|
|
104
|
+
uv run coverage report
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
`uv run coverage html` writes a detailed report in `htmlcov/`.
|
|
108
|
+
|
|
109
|
+
## Check the code
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
uv run ruff check .
|
|
113
|
+
uv run ruff format --check .
|
|
114
|
+
uv run pyright
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Documentation
|
|
118
|
+
|
|
119
|
+
The documentation is online at https://ryieru.github.io/numdaplot/. It is generated from the docstrings,
|
|
120
|
+
and shown locally with:
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
uv run mkdocs serve
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Release
|
|
127
|
+
|
|
128
|
+
A version is published by pushing a tag `v<version>`. The `Release` workflow then runs the checks, builds the
|
|
129
|
+
package, publishes it on TestPyPI, waits for an approval on GitHub, publishes it on PyPI, publishes the
|
|
130
|
+
documentation site and creates the GitHub release with the changes of `CHANGELOG.md`.
|
|
131
|
+
|
|
132
|
+
1. A minor or major version, such as `0.2.0` or `1.0.0`, is first tried as a release candidate: set
|
|
133
|
+
`version = "0.2.0rc1"` in `pyproject.toml`, commit, push, then push the tag. A release candidate only goes to
|
|
134
|
+
TestPyPI. Check its page and its installation, and fix with `0.2.0rc2` and so on until it is right.
|
|
135
|
+
2. Set the final version in `pyproject.toml`, and replace `## [Unreleased]` with `## [0.2.0] - <date>` in
|
|
136
|
+
`CHANGELOG.md`. Commit, push, then push the tag.
|
|
137
|
+
3. Check the version on TestPyPI, then approve the `pypi` environment in the workflow run on GitHub.
|
|
138
|
+
|
|
139
|
+
A patch version, such as `0.1.1`, skips step 1. When TestPyPI shows a problem, the approval is refused and the patch
|
|
140
|
+
is tried again as `0.1.1rc1`.
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
git tag v0.2.0rc1
|
|
144
|
+
git push origin v0.2.0rc1
|
|
145
|
+
pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ numdaplot==0.2.0rc1
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Code organization
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
src/numdaplot/
|
|
152
|
+
__init__.py every public name, available as ndp.*
|
|
153
|
+
arrays/ Array and its settings: Shape, Spacing, distributions, math functions...
|
|
154
|
+
tables/ Table and its settings: file options, Filter, Aggregation, PivotTable, Sorting, Preview...
|
|
155
|
+
dates/ DateFormat, TimeZone, TimeZoneChange, DatePart, DatePeriod, DurationIn, ToDuration...
|
|
156
|
+
plots/ Plot and its creation methods, the charts, the PlotStyle and Figure
|
|
157
|
+
errors/ NumdaplotError, the precise errors, NumdaplotWarning and the precise warnings
|
|
158
|
+
data_types/ the Type enum and its conversion to numpy and pandas dtypes
|
|
159
|
+
ratios/ validation of fractions between 0 and 1, and the Measure enum
|
|
160
|
+
rules/ tests applied to each value: Equal, Greater, Between, IsIn, Contains, IsMissing...
|
|
161
|
+
statistics/ Sum, Mean, Median, Quantile, StandardDeviation...
|
|
162
|
+
positions/ Region, Index, Range and Axis
|
|
163
|
+
ordering/ Order and MissingPosition
|
|
164
|
+
settings/ check of the settings against their annotations, InvalidTypeError being raised
|
|
165
|
+
tests/
|
|
166
|
+
unit/ one test file per source file, mirroring src/numdaplot
|
|
167
|
+
functional/ one test file per notion, using the library as ndp
|
|
168
|
+
docs/ pages and stylesheet of the documentation site
|
|
169
|
+
tools/docs/ griffe extensions and MkDocs hooks building the documentation site and its API pages
|
|
170
|
+
run_tests.py test entry point
|
|
171
|
+
conftest.py pytest settings shared by the tests and the docstring examples
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## License
|
|
175
|
+
|
|
176
|
+
BSD-3-Clause, see [LICENSE](https://github.com/Ryieru/numdaplot/blob/main/LICENSE).
|