IncludeCPP 3.4.0__tar.gz → 3.4.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. {includecpp-3.4.0 → includecpp-3.4.1}/IncludeCPP.egg-info/PKG-INFO +11 -2
  2. {includecpp-3.4.0 → includecpp-3.4.1}/PKG-INFO +11 -2
  3. {includecpp-3.4.0 → includecpp-3.4.1}/README.md +10 -1
  4. {includecpp-3.4.0 → includecpp-3.4.1}/includecpp/__init__.py +1 -1
  5. {includecpp-3.4.0 → includecpp-3.4.1}/includecpp/cli/commands.py +3 -1
  6. {includecpp-3.4.0 → includecpp-3.4.1}/includecpp/core/cppy_converter.py +101 -18
  7. {includecpp-3.4.0 → includecpp-3.4.1}/includecpp/generator/parser.cpp +41 -0
  8. {includecpp-3.4.0 → includecpp-3.4.1}/pyproject.toml +1 -1
  9. {includecpp-3.4.0 → includecpp-3.4.1}/setup.py +1 -1
  10. {includecpp-3.4.0 → includecpp-3.4.1}/IncludeCPP.egg-info/SOURCES.txt +0 -0
  11. {includecpp-3.4.0 → includecpp-3.4.1}/IncludeCPP.egg-info/dependency_links.txt +0 -0
  12. {includecpp-3.4.0 → includecpp-3.4.1}/IncludeCPP.egg-info/entry_points.txt +0 -0
  13. {includecpp-3.4.0 → includecpp-3.4.1}/IncludeCPP.egg-info/requires.txt +0 -0
  14. {includecpp-3.4.0 → includecpp-3.4.1}/IncludeCPP.egg-info/top_level.txt +0 -0
  15. {includecpp-3.4.0 → includecpp-3.4.1}/LICENSE +0 -0
  16. {includecpp-3.4.0 → includecpp-3.4.1}/MANIFEST.in +0 -0
  17. {includecpp-3.4.0 → includecpp-3.4.1}/includecpp/__init__.pyi +0 -0
  18. {includecpp-3.4.0 → includecpp-3.4.1}/includecpp/__main__.py +0 -0
  19. {includecpp-3.4.0 → includecpp-3.4.1}/includecpp/cli/__init__.py +0 -0
  20. {includecpp-3.4.0 → includecpp-3.4.1}/includecpp/cli/config_parser.py +0 -0
  21. {includecpp-3.4.0 → includecpp-3.4.1}/includecpp/core/__init__.py +0 -0
  22. {includecpp-3.4.0 → includecpp-3.4.1}/includecpp/core/ai_integration.py +0 -0
  23. {includecpp-3.4.0 → includecpp-3.4.1}/includecpp/core/build_manager.py +0 -0
  24. {includecpp-3.4.0 → includecpp-3.4.1}/includecpp/core/cpp_api.py +0 -0
  25. {includecpp-3.4.0 → includecpp-3.4.1}/includecpp/core/cpp_api.pyi +0 -0
  26. {includecpp-3.4.0 → includecpp-3.4.1}/includecpp/core/error_catalog.py +0 -0
  27. {includecpp-3.4.0 → includecpp-3.4.1}/includecpp/core/error_formatter.py +0 -0
  28. {includecpp-3.4.0 → includecpp-3.4.1}/includecpp/core/exceptions.py +0 -0
  29. {includecpp-3.4.0 → includecpp-3.4.1}/includecpp/core/path_discovery.py +0 -0
  30. {includecpp-3.4.0 → includecpp-3.4.1}/includecpp/core/project_ui.py +0 -0
  31. {includecpp-3.4.0 → includecpp-3.4.1}/includecpp/core/settings_ui.py +0 -0
  32. {includecpp-3.4.0 → includecpp-3.4.1}/includecpp/generator/__init__.py +0 -0
  33. {includecpp-3.4.0 → includecpp-3.4.1}/includecpp/generator/parser.h +0 -0
  34. {includecpp-3.4.0 → includecpp-3.4.1}/includecpp/generator/type_resolver.cpp +0 -0
  35. {includecpp-3.4.0 → includecpp-3.4.1}/includecpp/generator/type_resolver.h +0 -0
  36. {includecpp-3.4.0 → includecpp-3.4.1}/includecpp/py.typed +0 -0
  37. {includecpp-3.4.0 → includecpp-3.4.1}/includecpp/templates/cpp.proj.template +0 -0
  38. {includecpp-3.4.0 → includecpp-3.4.1}/requirements.txt +0 -0
  39. {includecpp-3.4.0 → includecpp-3.4.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: IncludeCPP
3
- Version: 3.4.0
3
+ Version: 3.4.1
4
4
  Summary: Professional C++ Python bindings with type-generic templates, pystubs and native threading
5
5
  Home-page: https://github.com/liliassg/IncludeCPP
6
6
  Author: Lilias Hatterscheidt
@@ -625,6 +625,15 @@ Use at your own discretion. Report issues at: https://github.com/hatte/IncludeCP
625
625
 
626
626
  # Changelog
627
627
 
628
+ ## v3.4.1
629
+ - **Bug Fixes:**
630
+ - fix command: Fixed false positives for unused variables (sum, memory_) using word-boundary matching
631
+ - CPPY: C++ reserved words (double, int, void, etc.) now properly escaped as Python identifiers
632
+ - CPPY: C++ STL functions (accumulate, find, sort, reverse) properly converted to Python equivalents
633
+ - CPPY: Member variables with trailing underscore (memory_) now get self. prefix
634
+ - CPPY: Private class members now detected for self. prefix conversion
635
+ - Plugin: Auto-detect header files from #include directives in source files
636
+
628
637
  ## v3.4.0
629
638
  - **CodeMaker Major Update:**
630
639
  - New Source node type with 8 connection ports for code generation
@@ -787,4 +796,4 @@ Use at your own discretion. Report issues at: https://github.com/hatte/IncludeCP
787
796
 
788
797
  ---
789
798
 
790
- MIT License | v3.4.0 | [GitHub](https://github.com/liliassg/IncludeCPP)
799
+ MIT License | v3.4.1 | [GitHub](https://github.com/liliassg/IncludeCPP)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: IncludeCPP
3
- Version: 3.4.0
3
+ Version: 3.4.1
4
4
  Summary: Professional C++ Python bindings with type-generic templates, pystubs and native threading
5
5
  Home-page: https://github.com/liliassg/IncludeCPP
6
6
  Author: Lilias Hatterscheidt
@@ -625,6 +625,15 @@ Use at your own discretion. Report issues at: https://github.com/hatte/IncludeCP
625
625
 
626
626
  # Changelog
627
627
 
628
+ ## v3.4.1
629
+ - **Bug Fixes:**
630
+ - fix command: Fixed false positives for unused variables (sum, memory_) using word-boundary matching
631
+ - CPPY: C++ reserved words (double, int, void, etc.) now properly escaped as Python identifiers
632
+ - CPPY: C++ STL functions (accumulate, find, sort, reverse) properly converted to Python equivalents
633
+ - CPPY: Member variables with trailing underscore (memory_) now get self. prefix
634
+ - CPPY: Private class members now detected for self. prefix conversion
635
+ - Plugin: Auto-detect header files from #include directives in source files
636
+
628
637
  ## v3.4.0
629
638
  - **CodeMaker Major Update:**
630
639
  - New Source node type with 8 connection ports for code generation
@@ -787,4 +796,4 @@ Use at your own discretion. Report issues at: https://github.com/hatte/IncludeCP
787
796
 
788
797
  ---
789
798
 
790
- MIT License | v3.4.0 | [GitHub](https://github.com/liliassg/IncludeCPP)
799
+ MIT License | v3.4.1 | [GitHub](https://github.com/liliassg/IncludeCPP)
@@ -591,6 +591,15 @@ Use at your own discretion. Report issues at: https://github.com/hatte/IncludeCP
591
591
 
592
592
  # Changelog
593
593
 
594
+ ## v3.4.1
595
+ - **Bug Fixes:**
596
+ - fix command: Fixed false positives for unused variables (sum, memory_) using word-boundary matching
597
+ - CPPY: C++ reserved words (double, int, void, etc.) now properly escaped as Python identifiers
598
+ - CPPY: C++ STL functions (accumulate, find, sort, reverse) properly converted to Python equivalents
599
+ - CPPY: Member variables with trailing underscore (memory_) now get self. prefix
600
+ - CPPY: Private class members now detected for self. prefix conversion
601
+ - Plugin: Auto-detect header files from #include directives in source files
602
+
594
603
  ## v3.4.0
595
604
  - **CodeMaker Major Update:**
596
605
  - New Source node type with 8 connection ports for code generation
@@ -753,4 +762,4 @@ Use at your own discretion. Report issues at: https://github.com/hatte/IncludeCP
753
762
 
754
763
  ---
755
764
 
756
- MIT License | v3.4.0 | [GitHub](https://github.com/liliassg/IncludeCPP)
765
+ MIT License | v3.4.1 | [GitHub](https://github.com/liliassg/IncludeCPP)
@@ -1,7 +1,7 @@
1
1
  from .core.cpp_api import CppApi
2
2
  import warnings
3
3
 
4
- __version__ = "3.4.0"
4
+ __version__ = "3.4.1"
5
5
  __all__ = ["CppApi"]
6
6
 
7
7
  # Module-level cache for C++ modules
@@ -4436,8 +4436,10 @@ def fix(module_name, all_modules, exclude, undo, auto_fix, verbose, use_ai):
4436
4436
  if var_decl:
4437
4437
  var_name = var_decl.group(1)
4438
4438
  # Check if variable appears again in rest of content
4439
+ # v3.4.1: Use word boundaries to avoid false positives from substring matches
4439
4440
  rest_content = '\n'.join(lines[i:])
4440
- if rest_content.count(var_name) <= 1:
4441
+ uses = len(re.findall(rf'\b{re.escape(var_name)}\b', rest_content))
4442
+ if uses <= 1:
4441
4443
  add_issue('info', 'Mistake', file_path, i, 'C003',
4442
4444
  f"Variable '{var_name}' may be unused",
4443
4445
  "Remove unused variable or mark as [[maybe_unused]]")
@@ -34,6 +34,24 @@ PYTHON_KEYWORDS = {
34
34
  'while', 'with', 'yield'
35
35
  }
36
36
 
37
+ # v3.4.1: C++ reserved words that need escaping when used as Python identifiers
38
+ # These are C++ types/keywords that are valid Python identifiers but confusing
39
+ CPP_RESERVED_WORDS = {
40
+ # Primitive types
41
+ 'int', 'float', 'double', 'char', 'bool', 'void', 'auto',
42
+ 'short', 'long', 'signed', 'unsigned', 'wchar_t',
43
+ # Type modifiers
44
+ 'const', 'static', 'virtual', 'volatile', 'mutable', 'extern',
45
+ 'register', 'inline', 'explicit', 'constexpr', 'consteval',
46
+ # Access modifiers
47
+ 'public', 'private', 'protected',
48
+ # Other keywords
49
+ 'template', 'typename', 'namespace', 'using', 'typedef',
50
+ 'struct', 'union', 'enum', 'sizeof', 'alignof', 'decltype',
51
+ 'new', 'delete', 'operator', 'friend', 'this',
52
+ 'throw', 'catch', 'noexcept', 'final', 'override',
53
+ }
54
+
37
55
 
38
56
  def _escape_python_keyword(name: str) -> str:
39
57
  """Escape Python reserved keywords by adding underscore suffix.
@@ -45,6 +63,27 @@ def _escape_python_keyword(name: str) -> str:
45
63
  return name
46
64
 
47
65
 
66
+ def _escape_cpp_reserved(name: str) -> str:
67
+ """Escape C++ reserved words when used as Python identifiers.
68
+
69
+ Example: 'double' -> 'double_', 'int' -> 'int_', 'void' -> 'void_'
70
+ v3.4.1: Prevents C++ type names from being used as Python function/variable names.
71
+ """
72
+ if name in CPP_RESERVED_WORDS:
73
+ return name + '_'
74
+ return name
75
+
76
+
77
+ def _escape_identifier(name: str) -> str:
78
+ """Escape both Python keywords and C++ reserved words.
79
+
80
+ Combines both escaping functions for comprehensive identifier safety.
81
+ """
82
+ name = _escape_python_keyword(name)
83
+ name = _escape_cpp_reserved(name)
84
+ return name
85
+
86
+
48
87
  # Python type to C++ type mapping
49
88
  PY_TO_CPP_TYPES = {
50
89
  'int': 'int',
@@ -2225,11 +2264,31 @@ class CppToPythonConverter:
2225
2264
 
2226
2265
  def _parse_class_fields(self, body: str) -> List[Tuple[str, str, Optional[str]]]:
2227
2266
  fields = []
2267
+ all_field_names = set() # v3.4.1: Track ALL fields for self. prefix
2228
2268
 
2269
+ # v3.4.1: Parse fields from ALL sections (public, private, protected)
2270
+ # for self. prefix detection, but only return public fields for dataclass
2229
2271
  sections = re.split(r'(?:public|private|protected)\s*:', body)
2230
- public_section = sections[1] if len(sections) > 1 else body
2231
2272
 
2232
2273
  field_pattern = r'(\w+(?:<[^>]+>)?)\s+(\w+)\s*(?:=\s*([^;]+))?\s*;'
2274
+
2275
+ # First pass: collect ALL field names from all sections
2276
+ for section in sections:
2277
+ for match in re.finditer(field_pattern, section):
2278
+ field_type = match.group(1)
2279
+ field_name = match.group(2)
2280
+
2281
+ if '(' in field_type or field_type in ('return', 'if', 'for', 'while'):
2282
+ continue
2283
+
2284
+ all_field_names.add(field_name)
2285
+
2286
+ # Store all field names for self. prefix detection
2287
+ self._current_class_fields = all_field_names
2288
+
2289
+ # Second pass: return only public fields for the Python class definition
2290
+ public_section = sections[1] if len(sections) > 1 else body
2291
+
2233
2292
  for match in re.finditer(field_pattern, public_section):
2234
2293
  field_type = match.group(1)
2235
2294
  field_name = match.group(2)
@@ -2594,13 +2653,30 @@ class CppToPythonConverter:
2594
2653
  expr = re.sub(r'std::max\(([^,]+),\s*([^)]+)\)', r'max(\1, \2)', expr)
2595
2654
 
2596
2655
  # Handle std::accumulate(container.begin(), container.end(), init) -> sum(container) [+ init]
2656
+ # v3.4.1: Also handle accumulate without std:: prefix
2597
2657
  def _accumulate_to_sum(m):
2598
2658
  container = m.group(1)
2599
2659
  init_val = m.group(2).strip()
2600
2660
  if init_val == '0' or init_val == '0.0':
2601
2661
  return f'sum({container})'
2602
2662
  return f'sum({container}) + {init_val}'
2603
- expr = re.sub(r'std::accumulate\((\w+)\.begin\(\),\s*\1\.end\(\),\s*([^)]+)\)', _accumulate_to_sum, expr)
2663
+ expr = re.sub(r'(?:std::)?accumulate\((\w+)\.begin\(\),\s*\1\.end\(\),\s*([^)]+)\)', _accumulate_to_sum, expr)
2664
+
2665
+ # v3.4.1: Handle std::find, std::count, std::sort with .begin()/.end()
2666
+ # std::find(vec.begin(), vec.end(), val) -> val in vec
2667
+ expr = re.sub(r'(?:std::)?find\((\w+)\.begin\(\),\s*\1\.end\(\),\s*([^)]+)\)\s*!=\s*\1\.end\(\)', r'\2 in \1', expr)
2668
+ # std::count(vec.begin(), vec.end(), val) -> vec.count(val)
2669
+ expr = re.sub(r'(?:std::)?count\((\w+)\.begin\(\),\s*\1\.end\(\),\s*([^)]+)\)', r'\1.count(\2)', expr)
2670
+ # std::sort(vec.begin(), vec.end()) -> vec.sort()
2671
+ expr = re.sub(r'(?:std::)?sort\((\w+)\.begin\(\),\s*\1\.end\(\)\)', r'\1.sort()', expr)
2672
+ # std::reverse(vec.begin(), vec.end()) -> vec.reverse()
2673
+ expr = re.sub(r'(?:std::)?reverse\((\w+)\.begin\(\),\s*\1\.end\(\)\)', r'\1.reverse()', expr)
2674
+
2675
+ # v3.4.1: Clean up any remaining .begin()/.end() that couldn't be converted
2676
+ # container.begin() -> iter(container) for iteration context
2677
+ # But typically these are errors - flag as comment if they remain
2678
+ expr = re.sub(r'(\w+)\.begin\(\)', r'\1[0]', expr) # Approximate as first element
2679
+ expr = re.sub(r'(\w+)\.end\(\)', r'len(\1)', expr) # Approximate as length
2604
2680
 
2605
2681
  # Handle .size() -> len()
2606
2682
  expr = re.sub(r'(\w+)\.size\(\)', r'len(\1)', expr)
@@ -2646,26 +2722,33 @@ class CppToPythonConverter:
2646
2722
  # Fixed lookahead to be more permissive - match non-word chars or end
2647
2723
  expr = re.sub(rf'(?<![.\w])(?<!self\.){re.escape(field)}(?=\W|$)', f'self.{field}', expr)
2648
2724
 
2649
- # v3.3.22: Also handle common C++ member naming conventions (m_* and _*)
2650
- # Convert m_name or _name to self.name when in class context
2725
+ # v3.4.1: Handle common C++ member naming conventions
2726
+ # Convert m_name to self.name when in class context
2651
2727
  if self._current_class_fields:
2652
2728
  # Convert m_xxx to self.xxx
2653
2729
  expr = re.sub(r'(?<![.\w])m_(\w+)(?=\W|$)', r'self.\1', expr)
2730
+ # Convert _xxx to self.xxx (leading underscore)
2731
+ expr = re.sub(r'(?<![.\w])_(\w+)(?=\W|$)', r'self.\1', expr)
2732
+ # v3.4.1: Convert xxx_ to self.xxx_ (trailing underscore - Google style)
2733
+ # Only if it's a known field or matches the pattern
2734
+ for field in self._current_class_fields:
2735
+ if field.endswith('_') and field not in ('self_',):
2736
+ expr = re.sub(rf'(?<![.\w]){re.escape(field)}(?=\W|$)', f'self.{field}', expr)
2654
2737
 
2655
2738
  return expr
2656
2739
 
2657
2740
  def _generate_struct(self, struct: StructInfo) -> List[str]:
2658
2741
  lines = ['@dataclass']
2659
- # v3.3.22: Escape Python keywords in struct/class names
2660
- struct_name = _escape_python_keyword(struct.name)
2742
+ # v3.4.1: Escape Python keywords and C++ reserved words in struct/class names
2743
+ struct_name = _escape_identifier(struct.name)
2661
2744
  lines.append(f'class {struct_name}:')
2662
2745
 
2663
2746
  if not struct.fields:
2664
2747
  lines.append(f'{self.indent}pass')
2665
2748
  else:
2666
2749
  for fname, ftype in struct.fields:
2667
- # v3.3.22: Escape Python keywords in field names
2668
- escaped_fname = _escape_python_keyword(fname)
2750
+ # v3.4.1: Escape Python keywords and C++ reserved words in field names
2751
+ escaped_fname = _escape_identifier(fname)
2669
2752
  lines.append(f'{self.indent}{escaped_fname}: {ftype}')
2670
2753
 
2671
2754
  return lines
@@ -2673,8 +2756,8 @@ class CppToPythonConverter:
2673
2756
  def _generate_class(self, cls: ClassInfo) -> List[str]:
2674
2757
  lines = []
2675
2758
 
2676
- # v3.3.22: Escape Python keywords in class names
2677
- class_name = _escape_python_keyword(cls.name)
2759
+ # v3.4.1: Escape Python keywords and C++ reserved words in class names
2760
+ class_name = _escape_identifier(cls.name)
2678
2761
  if cls.bases:
2679
2762
  lines.append(f'class {class_name}({", ".join(cls.bases)}):')
2680
2763
  else:
@@ -2700,8 +2783,8 @@ class CppToPythonConverter:
2700
2783
 
2701
2784
  params = ['self'] if not method.is_static else []
2702
2785
  for pname, ptype in method.params:
2703
- # v3.3.22: Escape Python keywords in parameter names
2704
- escaped_pname = _escape_python_keyword(pname)
2786
+ # v3.4.1: Escape Python keywords and C++ reserved words in parameter names
2787
+ escaped_pname = _escape_identifier(pname)
2705
2788
  if ptype and ptype != 'Any':
2706
2789
  params.append(f'{escaped_pname}: {ptype}')
2707
2790
  else:
@@ -2711,8 +2794,8 @@ class CppToPythonConverter:
2711
2794
  if not is_init and method.return_type and method.return_type != 'None':
2712
2795
  ret_type = f' -> {method.return_type}'
2713
2796
 
2714
- # v3.3.22: Escape Python keywords in method names
2715
- method_name = '__init__' if is_init else _escape_python_keyword(method.name)
2797
+ # v3.4.1: Escape Python keywords and C++ reserved words in method names
2798
+ method_name = '__init__' if is_init else _escape_identifier(method.name)
2716
2799
  lines.append(f'{self.indent}def {method_name}({", ".join(params)}){ret_type}:')
2717
2800
 
2718
2801
  body_lines = method.body.split('\n')
@@ -2729,8 +2812,8 @@ class CppToPythonConverter:
2729
2812
 
2730
2813
  params = []
2731
2814
  for pname, ptype in func.params:
2732
- # v3.3.22: Escape Python keywords in parameter names
2733
- escaped_pname = _escape_python_keyword(pname)
2815
+ # v3.4.1: Escape Python keywords and C++ reserved words in parameter names
2816
+ escaped_pname = _escape_identifier(pname)
2734
2817
  if ptype and ptype != 'Any':
2735
2818
  params.append(f'{escaped_pname}: {ptype}')
2736
2819
  else:
@@ -2740,8 +2823,8 @@ class CppToPythonConverter:
2740
2823
  if func.return_type and func.return_type != 'None':
2741
2824
  ret_type = f' -> {func.return_type}'
2742
2825
 
2743
- # v3.3.22: Escape Python keywords in function names
2744
- func_name = _escape_python_keyword(func.name)
2826
+ # v3.4.1: Escape Python keywords and C++ reserved words in function names
2827
+ func_name = _escape_identifier(func.name)
2745
2828
  lines.append(f'def {func_name}({", ".join(params)}){ret_type}:')
2746
2829
 
2747
2830
  body_lines = func.body.split('\n')
@@ -700,6 +700,47 @@ ModuleDescriptor API::parse_cp_file(const std::string& filepath) {
700
700
  validate_namespace_includecpp(desc.source_path, desc.module_name);
701
701
  }
702
702
 
703
+ // v3.4.1: Auto-detect header from #include directives in source file
704
+ if (!desc.has_header && !desc.source_path.empty()) {
705
+ std::ifstream source_file(desc.source_path);
706
+ if (source_file.is_open()) {
707
+ std::string line;
708
+ std::regex include_regex(R"(^\s*#include\s*"([^"]+\.h(?:pp)?)")");
709
+ std::smatch match;
710
+
711
+ while (std::getline(source_file, line)) {
712
+ if (std::regex_search(line, match, include_regex)) {
713
+ std::string header_name = match[1].str();
714
+ // Skip standard headers and pybind11 headers
715
+ if (header_name.find("pybind11") == std::string::npos &&
716
+ header_name.find("std") == std::string::npos) {
717
+ // Found a local header - construct the path
718
+ std::filesystem::path source_path(desc.source_path);
719
+ std::filesystem::path header_path = source_path.parent_path() / header_name;
720
+
721
+ // Check if the header file exists
722
+ if (std::filesystem::exists(header_path)) {
723
+ desc.header_path = header_path.string();
724
+ desc.has_header = true;
725
+ std::cout << "NOTE: Auto-detected header for '" << desc.module_name
726
+ << "': " << desc.header_path << std::endl;
727
+ break;
728
+ }
729
+ // Also try in include/ subdirectory
730
+ header_path = source_path.parent_path().parent_path() / "include" / header_name;
731
+ if (std::filesystem::exists(header_path)) {
732
+ desc.header_path = header_path.string();
733
+ desc.has_header = true;
734
+ std::cout << "NOTE: Auto-detected header for '" << desc.module_name
735
+ << "': " << desc.header_path << std::endl;
736
+ break;
737
+ }
738
+ }
739
+ }
740
+ }
741
+ }
742
+ }
743
+
703
744
  return desc;
704
745
  }
705
746
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "IncludeCPP"
7
- version = "3.4.0"
7
+ version = "3.4.1"
8
8
  description = "Professional C++ Python bindings with type-generic templates, pystubs and native threading"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -6,7 +6,7 @@ long_description = (this_directory / "README.md").read_text(encoding="utf-8")
6
6
 
7
7
  setup(
8
8
  name="IncludeCPP",
9
- version="3.4.0",
9
+ version="3.4.1",
10
10
  author="Lilias Hatterscheidt",
11
11
  author_email="lilias@includecpp.dev",
12
12
  description="Professional C++ Python bindings with type-generic templates and native threading",
File without changes
File without changes
File without changes
File without changes